@humwick/runner 0.130.4 → 0.130.6

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.
Files changed (217) hide show
  1. package/LICENSE +661 -167
  2. package/agent-bin/humwick +2 -2
  3. package/agent-bin/humwick-browser +4 -0
  4. package/hooks/fff-search-redirect/fff-search-redirect.cjs +1 -1
  5. package/hooks/web-tools-redirect/web-tools-redirect.cjs +2 -2
  6. package/package.json +8 -11
  7. package/plugins/browser/skills/playwright-cli/SKILL.md +8 -6
  8. package/plugins/claude/.claude-plugin/plugin.json +3 -3
  9. package/plugins/claude/claude-statusline-probe.cjs +26 -16
  10. package/plugins/claude/hooks/gate-run-guard.provisioned.mjs +47 -17
  11. package/plugins/claude/hooks/gate-run-guard.sh +3 -3
  12. package/plugins/claude/hooks/gate-run-guard.ts +5 -5
  13. package/plugins/claude/hooks/kill-guard.provisioned.mjs +1 -1
  14. package/plugins/claude/hooks/kill-guard.sh +4 -4
  15. package/plugins/claude/hooks/kill-guard.ts +2 -2
  16. package/plugins/claude/hooks/permission-request.sh +1 -1
  17. package/plugins/claude/hooks/post-compact.sh +1 -1
  18. package/plugins/claude/hooks/post-tool-use.sh +3 -3
  19. package/plugins/claude/hooks/pre-compact.sh +2 -2
  20. package/plugins/claude/hooks/read-only-bash-guard.sh +4 -4
  21. package/plugins/claude/hooks/relay-status.sh +32 -32
  22. package/plugins/claude/hooks/session-end.sh +2 -2
  23. package/plugins/claude/hooks/session-start.sh +3 -3
  24. package/plugins/claude/hooks/shell-trust.ts +1 -1
  25. package/plugins/claude/hooks/stop-failure.sh +2 -2
  26. package/plugins/claude/hooks/stop.sh +6 -6
  27. package/plugins/claude/hooks/subagent-skill-policy.cjs +8 -6
  28. package/plugins/claude/hooks/subagent-stop.sh +3 -3
  29. package/plugins/claude/hooks/user-prompt-submit.sh +1 -1
  30. package/plugins/claude/hooks/wait-loop-guard.ts +3 -3
  31. package/plugins/claude/monitors/monitors.json +2 -2
  32. package/plugins/claude/monitors/relay-monitor.provisioned.mjs +96 -62
  33. package/plugins/claude/monitors/relay-monitor.ts +5 -5
  34. package/plugins/claude/skills/label/SKILL.md +3 -3
  35. package/plugins/claude/skills/message/SKILL.md +5 -5
  36. package/plugins/claude/skills/react/SKILL.md +1 -1
  37. package/plugins/claude/skills/read-message/SKILL.md +4 -4
  38. package/plugins/claude/skills/reply/SKILL.md +5 -5
  39. package/plugins/claude/skills/send-claimable/SKILL.md +5 -5
  40. package/plugins/claude/skills/slice-first/SKILL.md +5 -3
  41. package/plugins/claude/skills/slice-first/references/plan-recipe.md +30 -29
  42. package/plugins/claude/skills/status/SKILL.md +3 -3
  43. package/plugins/claude/skills/tags/SKILL.md +5 -5
  44. package/plugins/claude/skills/task/SKILL.md +10 -10
  45. package/plugins/claude-output-style/.claude-plugin/plugin.json +1 -1
  46. package/plugins/claude-output-style/output-styles/{agent-relay.md → humwick.md} +1 -1
  47. package/plugins/codex/skills/guide/SKILL.md +3 -3
  48. package/plugins/codex/skills/label/SKILL.md +3 -3
  49. package/plugins/codex/skills/message/SKILL.md +5 -5
  50. package/plugins/codex/skills/react/SKILL.md +1 -1
  51. package/plugins/codex/skills/read-message/SKILL.md +4 -4
  52. package/plugins/codex/skills/reply/SKILL.md +5 -5
  53. package/plugins/codex/skills/send-claimable/SKILL.md +5 -5
  54. package/plugins/codex/skills/slice-first/SKILL.md +5 -3
  55. package/plugins/codex/skills/slice-first/references/plan-recipe.md +30 -29
  56. package/plugins/codex/skills/status/SKILL.md +3 -3
  57. package/plugins/codex/skills/tags/SKILL.md +5 -5
  58. package/plugins/codex/skills/task/SKILL.md +11 -10
  59. package/src/adapter.ts +95 -92
  60. package/src/adapters/claude-api.ts +8 -11
  61. package/src/adapters/claude-context-command.ts +1 -1
  62. package/src/adapters/claude-credentials.ts +7 -3
  63. package/src/adapters/claude-delivery-lanes.ts +2 -2
  64. package/src/adapters/claude-delivery.ts +16 -16
  65. package/src/adapters/claude-effort.ts +2 -2
  66. package/src/adapters/claude-exit.ts +2 -2
  67. package/src/adapters/claude-headless-mirror.ts +18 -2
  68. package/src/adapters/claude-headless-refusal.ts +3 -3
  69. package/src/adapters/claude-headless.ts +11 -10
  70. package/src/adapters/claude-launch-exit.ts +1 -1
  71. package/src/adapters/claude-monitor-delivery-plan.ts +36 -16
  72. package/src/adapters/claude-permission.ts +5 -5
  73. package/src/adapters/claude-prompt-gates.ts +9 -9
  74. package/src/adapters/claude-prompt-hook.ts +2 -2
  75. package/src/adapters/claude-session-capture.ts +6 -6
  76. package/src/adapters/claude-session-probe.ts +25 -25
  77. package/src/adapters/claude-shutdown.ts +11 -11
  78. package/src/adapters/claude-status-detectors.ts +31 -31
  79. package/src/adapters/claude-subagents.ts +7 -7
  80. package/src/adapters/claude-submit-confirmation.ts +6 -6
  81. package/src/adapters/claude-tmux.ts +43 -43
  82. package/src/adapters/claude-token-usage-capture.ts +5 -5
  83. package/src/adapters/claude-tool-policy.ts +7 -7
  84. package/src/adapters/claude-transcript.ts +24 -24
  85. package/src/adapters/claude.ts +100 -100
  86. package/src/adapters/codex-agent-message-capture.ts +26 -63
  87. package/src/adapters/codex-app-server.ts +1 -1
  88. package/src/adapters/codex-client.ts +9 -9
  89. package/src/adapters/codex-effective-config.ts +1 -1
  90. package/src/adapters/codex-launch-config.ts +5 -5
  91. package/src/adapters/codex-rollout-context.ts +2 -2
  92. package/src/adapters/codex-skill-discovery.ts +1 -1
  93. package/src/adapters/codex-token-usage-capture.ts +16 -16
  94. package/src/adapters/codex-tool-output.ts +4 -4
  95. package/src/adapters/codex-version.ts +3 -3
  96. package/src/adapters/codex.ts +64 -64
  97. package/src/adapters/opencode-api.ts +1 -1
  98. package/src/adapters/opencode-context.ts +20 -22
  99. package/src/adapters/opencode-model-registry.ts +7 -7
  100. package/src/adapters/opencode-provider.ts +8 -8
  101. package/src/adapters/opencode-provisioning.ts +30 -0
  102. package/src/adapters/opencode-server-retry.ts +1 -1
  103. package/src/adapters/opencode-soft-steer.ts +5 -5
  104. package/src/adapters/opencode-spawn.ts +18 -14
  105. package/src/adapters/opencode-token-usage-capture.ts +12 -12
  106. package/src/adapters/opencode-tool-events.ts +15 -15
  107. package/src/adapters/opencode.ts +232 -232
  108. package/src/adapters/project-shell.ts +11 -11
  109. package/src/adapters/service-access.ts +6 -6
  110. package/src/adapters/tmux-offload.ts +9 -9
  111. package/src/adapters/tool-summary.ts +5 -5
  112. package/src/agent-redact.ts +1 -1
  113. package/src/agent-runner/commands/dispatch.ts +10 -10
  114. package/src/agent-runner/commands/lifecycle.ts +2 -2
  115. package/src/agent-runner/commands/prompt.ts +19 -19
  116. package/src/agent-runner/credentials.ts +5 -5
  117. package/src/agent-runner/inbox.ts +1 -1
  118. package/src/agent-runner/lifecycle-milestones.ts +3 -3
  119. package/src/agent-runner/lifecycle-phase.ts +2 -2
  120. package/src/agent-runner/liveness-exchange.ts +4 -10
  121. package/src/agent-runner/registration.ts +8 -8
  122. package/src/agent-runner/runner-context.ts +9 -14
  123. package/src/agent-runner/session-mirror.ts +12 -12
  124. package/src/agent-runner/task-claims.ts +2 -2
  125. package/src/agent-runner/token-usage-coverage.ts +1 -1
  126. package/src/agent-runner/turn-report.ts +12 -12
  127. package/src/api-budget-accounting.ts +3 -3
  128. package/src/area-memory.ts +6 -6
  129. package/src/artifact-path-materialize.ts +1 -1
  130. package/src/async-guard.ts +5 -5
  131. package/src/attachment-cache.ts +17 -22
  132. package/src/background-script-reconcile.ts +6 -6
  133. package/src/bounded-log.ts +1 -1
  134. package/src/busy-reconciler.ts +22 -22
  135. package/src/claim-tracker.ts +3 -3
  136. package/src/claude-settings.ts +8 -8
  137. package/src/claude-system-prompt.ts +1 -1
  138. package/src/claude-workspace-trust.ts +1 -1
  139. package/src/config.ts +62 -61
  140. package/src/context-boundary.ts +5 -5
  141. package/src/context-command.ts +3 -3
  142. package/src/control-server.ts +32 -32
  143. package/src/delivery-result.ts +2 -2
  144. package/src/effort-command.ts +2 -2
  145. package/src/empty-turn.ts +22 -14
  146. package/src/free-port.ts +1 -1
  147. package/src/gate-run-config.ts +3 -3
  148. package/src/host-asset-plan.ts +24 -17
  149. package/src/host-claude-config-worker.ts +2 -2
  150. package/src/host-sources.ts +2 -2
  151. package/src/index.ts +16 -16
  152. package/src/launch-assembly.ts +94 -96
  153. package/src/liveness.ts +15 -15
  154. package/src/logger.ts +3 -3
  155. package/src/mcp-outbox.ts +3 -3
  156. package/src/mcp-preflight.ts +2 -2
  157. package/src/mcp-source-selection.ts +2 -2
  158. package/src/mcp-tool-deferral.ts +1 -1
  159. package/src/mcp-vault-env.ts +2 -2
  160. package/src/message-body-config/config.ts +4 -4
  161. package/src/mid-turn-delivery.ts +2 -2
  162. package/src/native-memory-lever.ts +8 -8
  163. package/src/outbox.ts +15 -15
  164. package/src/pending-permission-store.ts +1 -1
  165. package/src/profile-home.ts +19 -19
  166. package/src/profile-projection.ts +26 -24
  167. package/src/project-instructions.ts +5 -5
  168. package/src/provider-auth-warning.ts +17 -0
  169. package/src/provider-double.ts +1 -1
  170. package/src/provider-hold.ts +3 -3
  171. package/src/provider-home-marker.ts +1 -1
  172. package/src/provider-home-tombstone.ts +1 -1
  173. package/src/provider-input-queue.ts +2 -2
  174. package/src/provider-integration.ts +15 -13
  175. package/src/provider-setup.ts +15 -3
  176. package/src/providers.ts +1 -1
  177. package/src/provisioning.ts +37 -40
  178. package/src/question-decision.ts +2 -2
  179. package/src/quota.ts +0 -6
  180. package/src/rate-limit.ts +24 -13
  181. package/src/refused-prompt-store.ts +2 -2
  182. package/src/relay-injection-events.ts +2 -2
  183. package/src/relay-instructions.ts +5 -5
  184. package/src/relay-mcp-proxy.long-turn-e2e.ts +13 -13
  185. package/src/relay-mcp-proxy.ts +57 -58
  186. package/src/relay-mcp.ts +55 -69
  187. package/src/reply-obligation-cache.ts +9 -9
  188. package/src/response-capture-report.ts +9 -9
  189. package/src/response-routing.ts +1 -1
  190. package/src/runner-core.ts +209 -222
  191. package/src/runner-exit.ts +1 -1
  192. package/src/runner-helpers.ts +10 -10
  193. package/src/runner-insights.ts +4 -2
  194. package/src/runner-mcp-proxy.ts +3 -3
  195. package/src/runner-spawn-config.ts +3 -3
  196. package/src/runtime-token-file.ts +1 -1
  197. package/src/runtime-token-remint.ts +1 -1
  198. package/src/service-access.ts +2 -2
  199. package/src/session-destroy.ts +1 -1
  200. package/src/session-insights.ts +1 -1
  201. package/src/session-scratch.ts +24 -37
  202. package/src/spawn-input.ts +6 -6
  203. package/src/startup-config-fetch.ts +4 -4
  204. package/src/subreaper.ts +3 -5
  205. package/src/test-run-dedup.ts +13 -13
  206. package/src/transcript-context.ts +2 -2
  207. package/src/transport-errors.ts +1 -1
  208. package/src/turn-opener.ts +1 -1
  209. package/src/turn-reconcile-event.ts +2 -2
  210. package/src/vault-proxy-hop.ts +2 -2
  211. package/src/web-tools.ts +2 -2
  212. package/agent-bin/agent-relay-browser +0 -10
  213. package/plugins/claude/skills/disconnect/SKILL.md +0 -16
  214. package/plugins/claude/skills/pair/SKILL.md +0 -30
  215. package/plugins/codex/skills/disconnect/SKILL.md +0 -15
  216. package/plugins/codex/skills/pair/SKILL.md +0 -29
  217. package/src/adapters/provider-quota-harvest.ts +0 -76
@@ -1,7 +1,7 @@
1
1
  import { COORDINATOR_PROFILE_NAMES, errMessage, type OperatorDecisionFileInput, type HumwickHttpClient } from "@humwick/sdk";
2
2
 
3
- // #2914: a coordinator's AskUserQuestion becomes a durable operator decision (same store, dashboard card and
4
- // answer-as-message as relay_decision). Any other agent, or a failed file, keeps the live relayed question.
3
+ // a coordinator's AskUserQuestion becomes a durable operator decision (same store, dashboard card and
4
+ // answer-as-message as humwick_decision). Any other agent, or a failed file, keeps the live relayed question.
5
5
  export async function fileQuestionDecision(
6
6
  deps: { http: Pick<HumwickHttpClient, "fileDecision">; profile?: string; log(message: string): void },
7
7
  input: OperatorDecisionFileInput,
package/src/quota.ts CHANGED
@@ -1,21 +1,15 @@
1
1
  export {
2
2
  DEFAULT_PROVIDER_QUOTA_CONFIG,
3
3
  QuotaRetryAfterError,
4
- claudeRateLimitHeadersQuotaState,
5
4
  claudeUsageQuotaState,
6
- collectClaudeQuotaState,
7
5
  collectCodexQuotaSample,
8
6
  collectCodexQuotaState,
9
7
  codexRateLimitsQuotaState,
10
8
  credentialAccountKey,
11
- defaultClaudeConfigDir,
12
9
  defaultZaiCredentialsPath,
13
10
  normalizeProviderQuotaConfig,
14
11
  providerPayloadAccountKey,
15
- resolveClaudeQuotaIdentity,
16
- resolveClaudeStatuslineQuotaIdentity,
17
12
  resolveCodexQuotaIdentity,
18
- resolveStableClaudeQuotaIdentity,
19
13
  resolveStableCodexQuotaIdentity,
20
14
  resolveStableZaiQuotaIdentity,
21
15
  type ProviderQuotaIdentity,
package/src/rate-limit.ts CHANGED
@@ -1,4 +1,4 @@
1
- // #286 — shared rate-limit hold construction + Claude pane detection.
1
+ // shared rate-limit hold construction + Claude pane detection.
2
2
  //
3
3
  // Two detection arms feed the SAME provider-neutral `blocked` hold:
4
4
  // 1. The StopFailure hook (clean API-error turn-end: API-429/auth/billing) → control-server.
@@ -18,6 +18,7 @@ const MAX_RESET_AHEAD_MS = 7 * 24 * 60 * 60 * 1000;
18
18
 
19
19
  interface RateLimitHoldInput {
20
20
  errorType?: string;
21
+ usageLimitScope?: ProviderState["usageLimitScope"];
21
22
  kind?: "usage_limit" | "transient_overload";
22
23
  /** Unix ms the limit window resets, when known. */
23
24
  resetAt?: number;
@@ -25,7 +26,7 @@ interface RateLimitHoldInput {
25
26
  source?: string;
26
27
  }
27
28
 
28
- // #3577 — Claude reports a proxy that refused CONNECT as "Couldn't connect through your proxy
29
+ // Claude reports a proxy that refused CONNECT as "Couldn't connect through your proxy
29
30
  // (ERR_PROXY_TUNNEL)"; Agent Vault refuses an expired or revoked session with 407.
30
31
  const PROXY_AUTH_FAILURE_RE = /ERR_PROXY_TUNNEL|proxy authentication required|\b407\b[^\n]*proxy|proxy[^\n]*\b407\b/i;
31
32
 
@@ -64,6 +65,7 @@ export function buildRateLimitProviderState(input: RateLimitHoldInput): Provider
64
65
  ? "Holding briefly for provider overload; Humwick will retry with bounded backoff."
65
66
  : "Holding until the usage window resets; Humwick auto-resumes the agent.",
66
67
  kind,
68
+ ...(kind === "usage_limit" ? { usageLimitScope: input.usageLimitScope ?? "provider" } : {}),
67
69
  source: input.source ?? "claude",
68
70
  errorType: input.errorType ?? RATE_LIMIT_BLOCK_REASON,
69
71
  enteredAt: now,
@@ -94,7 +96,7 @@ const LIMIT_PHRASE_RE = /(?:hit (?:your|the)\s*(?:[\w-]+\s+)*limit|usage limit|\
94
96
  const RESET_AT_RE = /\bresets?\b(?:\s+at)?\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)?\s*(?:\(([^)]+)\))?/i;
95
97
  const TRY_AGAIN_RE = /\btry again in\s+(\d+)\s*(second|minute|hour|day)s?/i;
96
98
 
97
- // #1611 — the limit phrase and its reset/retry must sit on the same line or within this many
99
+ // the limit phrase and its reset/retry must sit on the same line or within this many
98
100
  // lines of each other. The pairing was originally allowed to span the WHOLE pane so a modal
99
101
  // wrapping across rows still matched; that made the two halves collectable from unrelated
100
102
  // places on screen. A modal wraps onto the very next row, so a tight window keeps the wrapped
@@ -123,7 +125,7 @@ export function parseClaudeRateLimitPane(text: string, nowMs: number = Date.now(
123
125
  }
124
126
 
125
127
  /**
126
- * #1611 — the usage-limit modal, distinguished from the agent's OWN pane output.
128
+ * the usage-limit modal, distinguished from the agent's OWN pane output.
127
129
  *
128
130
  * The capture (`capture-pane -S -80`) contains the agent's rendered conversation, so a
129
131
  * phrase test over the whole pane fires on any agent that WRITES about rate limits. It did:
@@ -144,7 +146,7 @@ export function parseClaudeRateLimitPane(text: string, nowMs: number = Date.now(
144
146
  * a false negative, which costs one retry via the resume sweep. That is the cheap direction:
145
147
  * a false positive marks a healthy agent blocked, and `isAgentUnavailable` (src/db/
146
148
  * agent-predicates.ts) then QUEUES its inbound messages until the fabricated reset — real
147
- * work idled on a fabricated signal. See #1611.
149
+ * work idled on a fabricated signal.
148
150
  */
149
151
  function parseClaudeUsageLimitModal(text: string, nowMs: number): PaneRateLimit | null {
150
152
  const block = livePaneBlock(text);
@@ -171,25 +173,33 @@ function parseClaudeUsageLimitModal(text: string, nowMs: number): PaneRateLimit
171
173
  return null;
172
174
  }
173
175
 
174
- // #2619 — account-level usage/quota walls as providers word them in an API error message (zai:
176
+ // account-level usage/quota walls as providers word them in an API error message (zai:
175
177
  // "Usage limit reached for 5 hour. Your limit will reset at 2026-09-24 03:47:08"). Narrower than
176
178
  // LIMIT_PHRASE_RE on purpose: a bare "rate limit" is a per-request throttle, not a quota wall.
177
- const USAGE_LIMIT_MESSAGE_RE = /usage limit|usage exceeded|quota|limit (?:will )?resets?\b|insufficient (?:balance|credits?)/i;
179
+ const USAGE_LIMIT_MESSAGE_RE = /usage limit|usage exceeded|quota|limit (?:will )?resets?\b/i;
180
+ // the money walls among them (Anthropic: "credit balance is too low", "You have reached your specified
181
+ // API usage limits. You will regain access on ..."). Only these zero a metered API budget; a throttle never does.
182
+ const CREDIT_WALL_MESSAGE_RE = /spend(?:ing)? limit|api usage limits?\b|credit balance[^\n]*too low|insufficient (?:balance|credits?)/i;
178
183
  const RESET_AT_TIMESTAMP_RE = /\bresets?\s+(?:at\s+)?(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?\s*(?:Z|[+-]\d{2}:?\d{2}))/i;
179
184
 
180
185
  type ProviderRefusal = { message: string; errorType?: string; statusCode?: number };
181
186
 
182
187
  /** An account-level usage/quota wall: retrying in-session or re-rolling the session cannot clear it. */
183
188
  export function isProviderUsageLimit(error: ProviderRefusal): boolean {
184
- return USAGE_LIMIT_MESSAGE_RE.test(error.message) || /quota|usage_limit|tier_limit/i.test(error.errorType ?? "");
189
+ return isProviderCreditWall(error) || USAGE_LIMIT_MESSAGE_RE.test(error.message) || /quota|usage_limit|tier_limit/i.test(error.errorType ?? "");
185
190
  }
186
191
 
187
- /** #2619 — a provider-wide overload (5xx): not a broken session, so never worth a re-roll. */
192
+ /** An account wall of money: exhausted credit or a reached spend limit. */
193
+ export function isProviderCreditWall(error: ProviderRefusal): boolean {
194
+ return CREDIT_WALL_MESSAGE_RE.test(error.message);
195
+ }
196
+
197
+ /** a provider-wide overload (5xx): not a broken session, so never worth a re-roll. */
188
198
  export function isProviderOverload(error: ProviderRefusal): boolean {
189
199
  return (error.statusCode !== undefined && error.statusCode >= 500) || /overload/i.test(error.errorType ?? "");
190
200
  }
191
201
 
192
- // #2619 — per-request throttle wording. Some providers send it on a non-429 status flagged
202
+ // per-request throttle wording. Some providers send it on a non-429 status flagged
193
203
  // non-retryable (zai: 403 "Rate limit exceeded"); it is still a throttle, never an auth/model failure.
194
204
  const THROTTLE_MESSAGE_RE = /rate[\s_-]?limit|too many requests|throttl/i;
195
205
 
@@ -206,7 +216,7 @@ function isProviderRateLimited(error: ProviderRefusal): boolean {
206
216
  }
207
217
 
208
218
  /**
209
- * #2619 — the hold a RETRYABLE provider API refusal (429 quota wall, 5xx overload) ends a turn in,
219
+ * the hold a RETRYABLE provider API refusal (429 quota wall, 5xx overload) ends a turn in,
210
220
  * instead of a terminal failure: a terminal `error` status resolves runner-core's provider exit,
211
221
  * which is how every zai/OpenCode session died ~10 min into a quota wall. The same
212
222
  * `blocked/rate_limit` hold the Claude arms raise: runner-core keeps it across the idle, the relay
@@ -214,10 +224,11 @@ function isProviderRateLimited(error: ProviderRefusal): boolean {
214
224
  */
215
225
  export function buildProviderRefusalHold(input: ProviderRefusal & { detail: string; source: string; resetAt?: number }, nowMs: number = Date.now()): ProviderState {
216
226
  const usageLimit = isProviderRateLimited(input);
217
- // A provider-stated reset (OpenCode's retry `next`, #2775) beats parsing one out of the message.
227
+ // A provider-stated reset beats parsing one out of the message.
218
228
  const resetAt = usageLimit ? clampReset(input.resetAt, nowMs) ?? providerLimitResetAt(input.message, nowMs) : undefined;
219
229
  return buildRateLimitProviderState({
220
230
  kind: usageLimit ? "usage_limit" : "transient_overload",
231
+ usageLimitScope: isProviderCreditWall(input) ? "credit" : isProviderUsageLimit(input) || resetAt !== undefined ? "provider" : "request",
221
232
  errorType: input.errorType ?? (input.statusCode !== undefined ? String(input.statusCode) : "provider_error"),
222
233
  message: input.detail,
223
234
  source: input.source,
@@ -258,7 +269,7 @@ function livePaneBlock(text: string): string[] {
258
269
  // Unlike the usage-limit modal, Claude Code renders a transient API error as a CONVERSATION
259
270
  // row (`● API Error: 529 Overloaded…`), i.e. in the body, above the composer — so the
260
271
  // positional gate above cannot apply here without losing the detection entirely.
261
- // #1611 — but the arm had the same own-output hole: the phrase was matched anywhere on any
272
+ // but the arm had the same own-output hole: the phrase was matched anywhere on any
262
273
  // line, so an agent rendering this file's diff or a quoted error tripped it (reproduced live:
263
274
  // the fragment `+ane("● API Error: 529 Ove` in a rendered patch marked the agent blocked).
264
275
  // Claude's own error row STARTS with the error, after nothing but its bullet/box chrome, so
@@ -5,12 +5,12 @@ import { join } from "node:path";
5
5
  import { sanitizeFsName } from "@humwick/sdk/fs-name";
6
6
  import { runnerOutboxDirFromEnv } from "./config";
7
7
 
8
- /** #2622: unconfirmed self-posts remain cancelled across restart, without an in-memory tombstone cap. */
8
+ /** unconfirmed self-posts remain cancelled across restart, without an in-memory tombstone cap. */
9
9
  export class RefusedPromptStore {
10
10
  private readonly db: Database;
11
11
 
12
12
  constructor(options: { agentId: string; dir?: string }) {
13
- const dir = options.dir ?? runnerOutboxDirFromEnv() ?? join(tmpdir(), "agent-relay-outbox");
13
+ const dir = options.dir ?? runnerOutboxDirFromEnv() ?? join(tmpdir(), "humwick-outbox");
14
14
  const name = sanitizeFsName(options.agentId, { replacement: "_", maxLen: 180, fallback: "agent" });
15
15
  if (dir !== ":memory:") mkdirSync(dir, { recursive: true });
16
16
  this.db = new Database(dir === ":memory:" ? dir : join(dir, `refused-prompts-${name}.sqlite`), { create: true });
@@ -51,7 +51,7 @@ function launchInjectionEvents(input: RunnerLaunchInjectionInput): KeyedRelayInj
51
51
  : event,
52
52
  }));
53
53
  }
54
- // #1565 P5.7 — the native-memory lever gets its OWN `memory`-category event (the channel #1612
54
+ // P5.7 — the native-memory lever gets its OWN `memory`-category event (the channel
55
55
  // established for the spawn-seam memory block), not a line in the tools summary: this decides
56
56
  // whether the agent has one memory store or two, and a SUPPRESSED lever must be visible even on
57
57
  // a launch that provisions nothing else and would otherwise return early below.
@@ -75,7 +75,7 @@ function launchInjectionEvents(input: RunnerLaunchInjectionInput): KeyedRelayInj
75
75
  },
76
76
  });
77
77
  }
78
- // #3025 — a host without agent-redact still launches the agent; that launch must say so loudly.
78
+ // a host without agent-redact still launches the agent; that launch must say so loudly.
79
79
  // Appended last, so readers that find the first "tools" event still get the provisioning summary.
80
80
  const redaction = assembled.redaction;
81
81
  const redactionEvents: KeyedRelayInjectionEvent[] = redaction.state === "unavailable" ? [{
@@ -19,14 +19,14 @@ export function profileAllowsRelayFeature(config: Pick<RunnerSpawnConfig, "agent
19
19
  }
20
20
 
21
21
  /**
22
- * First-turn briefing (availability + text together). #2836: no core copy — the core is
22
+ * First-turn briefing (availability + text together).: no core copy — the core is
23
23
  * server-composed, and hand-started runners get no Relay instructions at all.
24
24
  */
25
25
  export function resolveRelayContext(input: {
26
26
  slug: string;
27
27
  config?: Pick<RunnerSpawnConfig, "agentProfile">;
28
28
  mcpServers?: Record<string, ProvisioningMcpServer>;
29
- /** #3024 — the launch's Brave/Jina tools, named per provider in the steer. */
29
+ /** the launch's Brave/Jina tools, named per provider in the steer. */
30
30
  webTools?: { names: readonly WebToolName[]; claude: boolean };
31
31
  }): RelayContextResolution {
32
32
  if (input.config && !profileAllowsRelayFeature(input.config, "context")) {
@@ -47,7 +47,7 @@ export function claudeRelayManual(): string {
47
47
  /** One line per capability: Brave searches; the local reader fetches, with keyless Jina fallback. */
48
48
  export function webToolsSteer(names: readonly WebToolName[], claude: boolean): string {
49
49
  return names.map(name => name === "brave"
50
- ? `Web search: use ${claude ? "web_search on the agent-relay MCP server (load with ToolSearch)" : "web_search on the agent-relay MCP server"}. Relay tries Tavily, then budget-capped Brave. If the monthly cap is reached, report it; do not retry in a loop.`
50
+ ? `Web search: use ${claude ? "web_search on the humwick MCP server (load with ToolSearch)" : "web_search on the humwick MCP server"}. Relay tries Tavily, then budget-capped Brave. If the monthly cap is reached, report it; do not retry in a loop.`
51
51
  : renderRunnerTemplate("relay.web.fetch", {
52
52
  tools: webToolSteerRefs(name, claude), fallback: webToolSteerRefs(name, claude, true),
53
53
  })).join("\n");
@@ -62,7 +62,7 @@ export function claudeReadOnlyRelayContext(): string {
62
62
  }
63
63
 
64
64
  export function relayReplyActionText(messageId: number): string {
65
- return `relay_reply (messageId: ${messageId}, body: "<your reply>"). CLI fallback: agent-relay /reply ${messageId} "<your reply>"`;
65
+ return `humwick_reply (messageId: ${messageId}, body: "<your reply>"). CLI fallback: humwick /reply ${messageId} "<your reply>"`;
66
66
  }
67
67
 
68
68
  export function workspaceDepsNote(input: { mode?: string | null; depsMode?: string | null; installCommand?: string | null }): string {
@@ -92,7 +92,7 @@ export function workspaceSymlinksNote(linked: string[]): string {
92
92
  }
93
93
 
94
94
  export function workspaceDepsNoteFromEnv(env: Record<string, string | undefined> = process.env): string {
95
- const json = relayEnv(env, "AGENT_RELAY_WORKSPACE_JSON");
95
+ const json = relayEnv(env, "HUMWICK_WORKSPACE_JSON");
96
96
  if (!json) return "";
97
97
  try {
98
98
  const parsed = JSON.parse(json) as { mode?: string; branch?: string; baseRef?: string; deps?: { mode?: string; command?: string }; symlinks?: { linked?: string[] } };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * #2429 / #2537 — opt-in compressed long-turn E2E for the shared MCP tool-call forward.
2
+ * opt-in compressed long-turn E2E for the shared MCP tool-call forward.
3
3
  *
4
- * Spawned as a CHILD bun process by the AGENT_RELAY_LONG_TURN_E2E=1-gated test in
4
+ * Spawned as a CHILD bun process by the HUMWICK_LONG_TURN_E2E=1-gated test in
5
5
  * relay-mcp-proxy.test.ts, with BUN_CONFIG_HTTP_IDLE_TIMEOUT=2 compressing Bun's native
6
6
  * ~300s HTTP idle watchdog down to ~2s for this process. A stand-in relay withholds ALL
7
7
  * response bytes for 6s (mimicking src/mcp/index.ts `tools/call`, which awaits the WHOLE
@@ -10,14 +10,14 @@
10
10
  * CONTROL — a plain fetch (no `timeout` option) against the slow relay must die with
11
11
  * TimeoutError: proves this process's idle watchdog is live and would abort
12
12
  * any >idle-timeout forward, i.e. the pre-fix behavior of forward().
13
- * REAL PATH — a long `relay_run` `tools/call` through the REAL RelayMcpProxy (whose
13
+ * REAL PATH — a long `humwick_run` `tools/call` through the REAL HumwickMcpProxy (whose
14
14
  * forward() sets `timeout:false`) must complete with the usable
15
15
  * `still-running` + `runId` envelope despite sitting silent well past the
16
16
  * compressed idle timeout.
17
17
  *
18
18
  * Exits 0 and prints LONG-TURN E2E PASS on success; non-zero with diagnostics otherwise.
19
19
  */
20
- import { RelayMcpProxy } from "./relay-mcp-proxy";
20
+ import { HumwickMcpProxy } from "./relay-mcp-proxy";
21
21
 
22
22
  const WITHHOLD_MS = 6_000;
23
23
  const SECRET = "long-turn-e2e-secret";
@@ -69,9 +69,9 @@ const slowRelay = Bun.serve({
69
69
  // Keep the intentionally silent response shape even for malformed control input.
70
70
  }
71
71
  await Bun.sleep(WITHHOLD_MS);
72
- if (!request || request.method !== "tools/call" || request.params?.name !== "relay_run") {
72
+ if (!request || request.method !== "tools/call" || request.params?.name !== "humwick_run") {
73
73
  return Response.json(
74
- { jsonrpc: "2.0", id, error: { code: -32601, message: "expected relay_run tools/call" } },
74
+ { jsonrpc: "2.0", id, error: { code: -32601, message: "expected humwick_run tools/call" } },
75
75
  { status: 400 },
76
76
  );
77
77
  }
@@ -85,7 +85,7 @@ const slowRelay = Bun.serve({
85
85
  jsonrpc: "2.0",
86
86
  id,
87
87
  result: {
88
- content: [{ type: "text", text: "relay_run still running" }],
88
+ content: [{ type: "text", text: "humwick_run still running" }],
89
89
  structuredContent: {
90
90
  run: {
91
91
  runId: "long-turn-run-id",
@@ -121,7 +121,7 @@ async function controlPlainFetchMustTimeOut(relayUrl: string): Promise<void> {
121
121
  }
122
122
 
123
123
  async function proxyForwardMustComplete(): Promise<void> {
124
- const proxy = new RelayMcpProxy({
124
+ const proxy = new HumwickMcpProxy({
125
125
  relayMcpEndpoint: `http://127.0.0.1:${slowRelay.port}/api/mcp`,
126
126
  getToken: () => "long-turn-e2e-live-token",
127
127
  authSecret: SECRET,
@@ -132,7 +132,7 @@ async function proxyForwardMustComplete(): Promise<void> {
132
132
  const startedAt = Date.now();
133
133
  // The agent-facing hop is NOT under test here (in production it does not run under the
134
134
  // compressed env), so it also opts out of the watchdog to avoid a false failure; the hop
135
- // being verified is forward() inside the proxy, whose fetch carries the #2429 fix.
135
+ // being verified is forward inside the proxy, whose fetch carries the fix.
136
136
  const agentSideInit: RequestInit & { timeout?: number | false } = {
137
137
  method: "POST",
138
138
  headers: { "content-type": "application/json", authorization: `Bearer ${SECRET}` },
@@ -141,7 +141,7 @@ async function proxyForwardMustComplete(): Promise<void> {
141
141
  id: "long-turn-1",
142
142
  method: "tools/call",
143
143
  params: {
144
- name: "relay_run",
144
+ name: "humwick_run",
145
145
  // A real maximum inline window is intentionally longer than this child's compressed
146
146
  // watchdog. The stand-in withholds the envelope for 6s, while its unconfigured
147
147
  // watchdog dies at ~2-4s, reproducing the pre-fix no-runId failure shape.
@@ -160,13 +160,13 @@ async function proxyForwardMustComplete(): Promise<void> {
160
160
  };
161
161
  if (!res.ok || !body.result) {
162
162
  fail(`proxy forward returned status ${res.status} body ${JSON.stringify(body)} — forward() `
163
- + "did not survive the idle watchdog; is the #2429 `timeout:false` flag present?");
163
+ + "did not survive the idle watchdog; is the `timeout:false` flag present?");
164
164
  }
165
165
  const run = body.result?.structuredContent?.run;
166
166
  if (run?.runId !== "long-turn-run-id" || run.status !== "still-running" || run.exitCode !== null) {
167
- fail(`relay_run did not return a usable still-running + runId envelope: ${JSON.stringify(body.result)}`);
167
+ fail(`humwick_run did not return a usable still-running + runId envelope: ${JSON.stringify(body.result)}`);
168
168
  }
169
- console.log(`real path: relay_run returned still-running + runId after ${Date.now() - startedAt}ms`);
169
+ console.log(`real path: humwick_run returned still-running + runId after ${Date.now() - startedAt}ms`);
170
170
  } finally {
171
171
  proxy.stop();
172
172
  }