@rallycry/conveyor-agent 10.8.2 → 10.10.0

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.
@@ -2,6 +2,13 @@ import {
2
2
  LoopLagMonitor
3
3
  } from "./chunk-7TQO4ZF4.js";
4
4
 
5
+ // src/utils/sleep.ts
6
+ function sleep(ms) {
7
+ return new Promise((resolve) => {
8
+ setTimeout(resolve, ms);
9
+ });
10
+ }
11
+
5
12
  // src/setup/bootstrap.ts
6
13
  var BOOTSTRAP_TIMEOUT_MS = 3e4;
7
14
  var RETRY_DELAYS_MS = [5e3, 1e4, 2e4];
@@ -37,11 +44,6 @@ async function singleBootstrapAttempt(apiUrl, instanceName, bootstrapToken, time
37
44
  clearTimeout(timer);
38
45
  }
39
46
  }
40
- async function sleep(ms) {
41
- await new Promise((resolve) => {
42
- setTimeout(resolve, ms);
43
- });
44
- }
45
47
  function buildFailure(reason, attempts, status, detail) {
46
48
  const out = { ok: false, reason, attempts };
47
49
  if (status === void 0) {
@@ -133,11 +135,6 @@ var PollUntilBoundHttpError = class extends Error {
133
135
  }
134
136
  status;
135
137
  };
136
- async function sleep2(ms) {
137
- await new Promise((resolve) => {
138
- setTimeout(resolve, ms);
139
- });
140
- }
141
138
  async function pollUntilBound(opts) {
142
139
  const pollIntervalMs = opts.pollIntervalMs ?? 2e3;
143
140
  const maxWaitMs = opts.maxWaitMs ?? 30 * 60 * 1e3;
@@ -153,7 +150,7 @@ async function pollUntilBound(opts) {
153
150
  if (Date.now() >= deadline) {
154
151
  throw new Error(`pollUntilBound timed out after ${maxWaitMs}ms waiting for pod bind`);
155
152
  }
156
- await sleep2(pollIntervalMs);
153
+ await sleep(pollIntervalMs);
157
154
  continue;
158
155
  }
159
156
  throw new PollUntilBoundHttpError(response.status);
@@ -951,6 +948,19 @@ var AgentConnection = class _AgentConnection {
951
948
  }).catch(() => {
952
949
  });
953
950
  }
951
+ /**
952
+ * The session's key hit a hard usage cap — ask the server to stamp it
953
+ * limited and hand back the best remaining key's credential env (or a
954
+ * requeue confirmation when none is left). Awaited: the caller swaps
955
+ * credentials and resumes on success, so it needs the real response.
956
+ */
957
+ async cycleCodingAgentKey(rateLimitType, resetsAt) {
958
+ return await this.call("cycleCodingAgentKey", {
959
+ sessionId: this.config.sessionId,
960
+ rateLimitType,
961
+ ...resetsAt ? { resetsAt } : {}
962
+ });
963
+ }
954
964
  // ── Question handling ──────────────────────────────────────────────
955
965
  async askUserQuestion(questions) {
956
966
  const questionText = questions.map(
@@ -1890,6 +1900,7 @@ async function restoreOnBoot(bundle, cwd) {
1890
1900
  // ../shared/dist/index.js
1891
1901
  import { z } from "zod";
1892
1902
  import { z as z2 } from "zod";
1903
+ import { z as z3 } from "zod";
1893
1904
  var DEFAULT_SONNET_MODEL = "claude-sonnet-5";
1894
1905
  var FABLE_MODEL = "claude-fable-5";
1895
1906
  var TUI_KINDS = ["claude-code", "opencode"];
@@ -1897,779 +1908,892 @@ var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
1897
1908
  var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
1898
1909
  var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
1899
1910
  var IDLE_HEARTBEAT_MS = 90 * 1e3;
1900
- var AgentHeartbeatSchema = z.object({
1901
- sessionId: z.string().optional(),
1902
- timestamp: z.string(),
1903
- status: z.enum(["active", "idle", "building"]),
1904
- currentAction: z.string().optional(),
1911
+ var TurnEndToolCallSchema = z.object({
1912
+ tool: z.string(),
1913
+ input: z.string().optional(),
1914
+ output: z.string().optional(),
1915
+ timestamp: z.string().optional()
1916
+ }).passthrough();
1917
+ var KnownAgentEventSchema = z.discriminatedUnion("type", [
1918
+ // ── Lifecycle / connection ────────────────────────────────────────────
1919
+ z.object({
1920
+ type: z.literal("connected"),
1921
+ sessionId: z.string(),
1922
+ projectId: z.string().optional()
1923
+ }).passthrough(),
1924
+ // Open-ended context snapshot spread from buildInitializationContext().
1925
+ z.object({ type: z.literal("session_manifest") }).passthrough(),
1926
+ z.object({
1927
+ type: z.literal("agent_runner_status"),
1928
+ reason: z.string(),
1929
+ attempt: z.number().optional(),
1930
+ attempts: z.number().optional()
1931
+ }).passthrough(),
1932
+ z.object({ type: z.literal("shutdown"), reason: z.string().optional() }).passthrough(),
1933
+ z.object({ type: z.literal("mode_changed"), agentMode: z.string() }).passthrough(),
1934
+ z.object({ type: z.literal("mode_transition"), from: z.string(), to: z.string() }).passthrough(),
1935
+ // ── Turn stream ───────────────────────────────────────────────────────
1936
+ z.object({ type: z.literal("message"), content: z.string() }).passthrough(),
1937
+ z.object({ type: z.literal("thinking"), message: z.string() }).passthrough(),
1938
+ z.object({
1939
+ type: z.literal("tool_use"),
1940
+ tool: z.string(),
1941
+ // Producers send JSON.stringify(input); consumers defend against
1942
+ // object inputs from older agents, so the wire stays permissive here.
1943
+ input: z.unknown().optional()
1944
+ }).passthrough(),
1945
+ z.object({
1946
+ type: z.literal("tool_result"),
1947
+ tool: z.string(),
1948
+ output: z.unknown().optional(),
1949
+ isError: z.boolean().optional(),
1950
+ redactedCount: z.number().optional()
1951
+ }).passthrough(),
1952
+ z.object({ type: z.literal("turn_end"), toolCalls: z.array(TurnEndToolCallSchema) }).passthrough(),
1953
+ z.object({
1954
+ type: z.literal("completed"),
1955
+ summary: z.string().optional(),
1956
+ durationMs: z.number().optional()
1957
+ }).passthrough(),
1958
+ z.object({ type: z.literal("error"), message: z.string() }).passthrough(),
1959
+ z.object({ type: z.literal("agent_typing_start") }).passthrough(),
1960
+ z.object({ type: z.literal("agent_typing_stop") }).passthrough(),
1961
+ // ── Telemetry ─────────────────────────────────────────────────────────
1962
+ // heartbeat/typing: legacy telemetry the server still classifies as
1963
+ // transient (TRANSIENT_EVENT_TYPES) — kept in the vocabulary.
1964
+ z.object({ type: z.literal("heartbeat") }).passthrough(),
1965
+ z.object({ type: z.literal("typing") }).passthrough(),
1966
+ z.object({
1967
+ type: z.literal("context_update"),
1968
+ contextTokens: z.number(),
1969
+ contextWindow: z.number(),
1970
+ inputTokens: z.number().optional(),
1971
+ cacheReadInputTokens: z.number().optional(),
1972
+ cacheCreationInputTokens: z.number().optional(),
1973
+ totalTokensUsed: z.number().optional()
1974
+ }).passthrough(),
1975
+ // Two producer shapes share this type: {rateLimitType, utilization, status}
1976
+ // (SDK rate_limit_event) and {resetsAt} (agent-connection resume notice).
1977
+ z.object({
1978
+ type: z.literal("rate_limit_update"),
1979
+ rateLimitType: z.string().optional(),
1980
+ utilization: z.number().optional(),
1981
+ status: z.string().optional(),
1982
+ resetsAt: z.string().optional()
1983
+ }).passthrough(),
1984
+ z.object({
1985
+ type: z.literal("context_compacted"),
1986
+ trigger: z.string().optional(),
1987
+ preTokens: z.number().optional()
1988
+ }).passthrough(),
1989
+ z.object({
1990
+ type: z.literal("tool_progress"),
1991
+ toolName: z.string().optional(),
1992
+ elapsedSeconds: z.number().optional()
1993
+ }).passthrough(),
1994
+ z.object({
1995
+ type: z.literal("subagent_started"),
1996
+ sdkTaskId: z.string().optional(),
1997
+ description: z.string().optional()
1998
+ }).passthrough(),
1999
+ z.object({
2000
+ type: z.literal("subagent_progress"),
2001
+ sdkTaskId: z.string().optional(),
2002
+ description: z.string().optional(),
2003
+ toolUses: z.number().optional(),
2004
+ durationMs: z.number().optional()
2005
+ }).passthrough(),
2006
+ // ── Work products ─────────────────────────────────────────────────────
2007
+ z.object({ type: z.literal("pr_created"), url: z.string(), number: z.number() }).passthrough(),
2008
+ z.object({
2009
+ type: z.literal("code_review_complete"),
2010
+ result: z.enum(["approved", "changes_requested"]),
2011
+ summary: z.string().optional(),
2012
+ issues: z.array(
2013
+ z.object({
2014
+ file: z.string(),
2015
+ line: z.number().optional(),
2016
+ severity: z.string().optional(),
2017
+ description: z.string().optional()
2018
+ }).passthrough()
2019
+ ).optional()
2020
+ }).passthrough(),
2021
+ // ── Environment setup / start command ─────────────────────────────────
2022
+ z.object({ type: z.literal("setup_output"), stream: z.string(), data: z.string() }).passthrough(),
2023
+ z.object({
2024
+ type: z.literal("setup_complete"),
2025
+ startCommandRunning: z.boolean().optional(),
2026
+ // Sanitized server-side by sanitizeSessionPreviewPorts — stays unknown.
2027
+ previewPorts: z.unknown().optional()
2028
+ }).passthrough(),
2029
+ z.object({ type: z.literal("setup_error"), message: z.string() }).passthrough(),
2030
+ z.object({ type: z.literal("start_command_started") }).passthrough(),
2031
+ z.object({ type: z.literal("start_command_output"), stream: z.string(), data: z.string() }).passthrough(),
2032
+ z.object({
2033
+ type: z.literal("start_command_exited"),
2034
+ code: z.number().nullable().optional(),
2035
+ signal: z.string().nullable().optional(),
2036
+ message: z.string().optional()
2037
+ }).passthrough(),
2038
+ z.object({ type: z.literal("start_command_error"), message: z.string() }).passthrough()
2039
+ ]);
2040
+ var AgentEventSchema = z.union([
2041
+ KnownAgentEventSchema,
2042
+ z.object({ type: z.string().min(1) }).catchall(z.unknown())
2043
+ ]);
2044
+ var AgentHeartbeatSchema = z2.object({
2045
+ sessionId: z2.string().optional(),
2046
+ timestamp: z2.string(),
2047
+ status: z2.enum(["active", "idle", "building"]),
2048
+ currentAction: z2.string().optional(),
1905
2049
  /** Sender-observed main event-loop lag (ms) — see AgentHeartbeat.loopLagMs. */
1906
- loopLagMs: z.number().nonnegative().optional()
2050
+ loopLagMs: z2.number().nonnegative().optional()
1907
2051
  });
1908
- var CreatePRInputSchema = z.object({
1909
- title: z.string().min(1),
1910
- body: z.string(),
1911
- head: z.string().optional(),
1912
- base: z.string().optional()
2052
+ var CreatePRInputSchema = z2.object({
2053
+ title: z2.string().min(1),
2054
+ body: z2.string(),
2055
+ head: z2.string().optional(),
2056
+ base: z2.string().optional()
1913
2057
  });
1914
- var PostToChatInputSchema = z.object({
1915
- message: z.string().min(1),
1916
- type: z.enum(["message", "question", "update"]).optional().default("message")
2058
+ var PostToChatInputSchema = z2.object({
2059
+ message: z2.string().min(1),
2060
+ type: z2.enum(["message", "question", "update"]).optional().default("message")
1917
2061
  });
1918
- var GetTaskContextRequestSchema = z.object({
1919
- sessionId: z.string(),
1920
- includeHistory: z.boolean().optional().default(false)
2062
+ var GetTaskContextRequestSchema = z2.object({
2063
+ sessionId: z2.string(),
2064
+ includeHistory: z2.boolean().optional().default(false)
1921
2065
  });
1922
- var GetChatMessagesRequestSchema = z.object({
1923
- sessionId: z.string(),
1924
- limit: z.number().int().positive().optional().default(50),
1925
- offset: z.number().int().nonnegative().optional().default(0)
2066
+ var GetChatMessagesRequestSchema = z2.object({
2067
+ sessionId: z2.string(),
2068
+ limit: z2.number().int().positive().optional().default(50),
2069
+ offset: z2.number().int().nonnegative().optional().default(0)
1926
2070
  });
1927
- var GetTaskFilesRequestSchema = z.object({
1928
- sessionId: z.string()
2071
+ var GetTaskFilesRequestSchema = z2.object({
2072
+ sessionId: z2.string()
1929
2073
  });
1930
- var GetTaskFileRequestSchema = z.object({
1931
- sessionId: z.string(),
1932
- fileId: z.string()
2074
+ var GetTaskFileRequestSchema = z2.object({
2075
+ sessionId: z2.string(),
2076
+ fileId: z2.string()
1933
2077
  });
1934
- var GetTaskRequestSchema = z.object({
1935
- sessionId: z.string(),
1936
- taskSlugOrId: z.string()
2078
+ var GetTaskRequestSchema = z2.object({
2079
+ sessionId: z2.string(),
2080
+ taskSlugOrId: z2.string()
1937
2081
  });
1938
- var GetCliHistoryRequestSchema = z.object({
1939
- sessionId: z.string(),
1940
- limit: z.number().int().positive().optional().default(100),
1941
- source: z.enum(["agent", "application"]).optional()
2082
+ var GetCliHistoryRequestSchema = z2.object({
2083
+ sessionId: z2.string(),
2084
+ limit: z2.number().int().positive().optional().default(100),
2085
+ source: z2.enum(["agent", "application"]).optional()
1942
2086
  });
1943
- var ListSubtasksRequestSchema = z.object({
1944
- sessionId: z.string(),
2087
+ var ListSubtasksRequestSchema = z2.object({
2088
+ sessionId: z2.string(),
1945
2089
  /** "compact" returns the slim orchestration view (ListSubtasksCompactResponse)
1946
2090
  * with the pack build-slot picture; "full" (default — wire-compat with older
1947
2091
  * agents) returns the verbose SubtaskSummaryDTO[] including description/plan. */
1948
- view: z.enum(["compact", "full"]).optional()
1949
- });
1950
- var GetDependenciesRequestSchema = z.object({
1951
- sessionId: z.string()
1952
- });
1953
- var GetSuggestionsRequestSchema = z.object({
1954
- sessionId: z.string(),
1955
- status: z.string().optional(),
1956
- limit: z.number().int().min(1).max(100).optional()
1957
- });
1958
- var ListManualTestsRequestSchema = z.object({
1959
- sessionId: z.string()
1960
- });
1961
- var QueryManualTestsRequestSchema = z.object({
1962
- sessionId: z.string(),
1963
- cardStatuses: z.array(z.string()).optional(),
1964
- testStatuses: z.array(z.enum(["open", "approved", "rejected"])).optional()
1965
- });
1966
- var CreatePullRequestRequestSchema = CreatePRInputSchema.extend({ sessionId: z.string() });
1967
- var RequestFileUploadRequestSchema = z.object({
1968
- sessionId: z.string(),
1969
- fileName: z.string().min(1).max(255),
1970
- mimeType: z.string().min(1).max(128),
1971
- fileSize: z.number().int().positive().max(MAX_FILE_SIZE_BYTES)
1972
- });
1973
- var ConfirmFileUploadRequestSchema = z.object({
1974
- sessionId: z.string(),
1975
- fileId: z.string(),
1976
- title: z.string().max(500).optional()
1977
- });
1978
- var UpdateTaskStatusRequestSchema = z.object({
1979
- sessionId: z.string(),
1980
- status: z.string(),
1981
- force: z.boolean().optional().default(false)
1982
- });
1983
- var StoreSessionIdRequestSchema = z.object({
1984
- sessionId: z.string(),
1985
- sdkSessionId: z.string()
1986
- });
1987
- var SetManualTestsRequestSchema = z.object({
1988
- sessionId: z.string(),
1989
- items: z.array(z.object({ title: z.string().min(1) })).min(1)
1990
- });
1991
- var EditManualTestRequestSchema = z.object({
1992
- sessionId: z.string(),
1993
- title: z.string().min(1),
1994
- newTitle: z.string().min(1)
1995
- });
1996
- var RemoveManualTestRequestSchema = z.object({
1997
- sessionId: z.string(),
1998
- title: z.string().min(1)
1999
- });
2000
- var ApproveManualTestRequestSchema = z.object({
2001
- sessionId: z.string(),
2002
- title: z.string().min(1)
2003
- });
2004
- var RejectManualTestRequestSchema = z.object({
2005
- sessionId: z.string(),
2006
- title: z.string().min(1),
2007
- reason: z.string().min(1).max(2e3)
2008
- });
2009
- var TrackSpendingRequestSchema = z.object({
2010
- sessionId: z.string(),
2011
- inputTokens: z.number().int().nonnegative(),
2012
- outputTokens: z.number().int().nonnegative(),
2013
- costUsd: z.number().nonnegative(),
2014
- model: z.string()
2015
- });
2016
- var SessionStartRequestSchema = z.object({
2017
- sessionId: z.string(),
2018
- agentVersion: z.string(),
2019
- capabilities: z.array(z.string())
2020
- });
2021
- var SessionStopRequestSchema = z.object({
2022
- sessionId: z.string(),
2023
- reason: z.string().optional()
2024
- });
2025
- var EndReviewSessionRequestSchema = z.object({
2026
- sessionId: z.string(),
2027
- reason: z.enum(["approved", "changes_requested", "finished"]).optional()
2028
- });
2029
- var ConnectAgentRequestSchema = z.object({
2030
- sessionId: z.string()
2031
- });
2032
- var ReportAgentStatusRequestSchema = z.object({
2033
- sessionId: z.string(),
2034
- status: z.string(),
2092
+ view: z2.enum(["compact", "full"]).optional()
2093
+ });
2094
+ var GetDependenciesRequestSchema = z2.object({
2095
+ sessionId: z2.string()
2096
+ });
2097
+ var GetSuggestionsRequestSchema = z2.object({
2098
+ sessionId: z2.string(),
2099
+ status: z2.string().optional(),
2100
+ limit: z2.number().int().min(1).max(100).optional()
2101
+ });
2102
+ var ListManualTestsRequestSchema = z2.object({
2103
+ sessionId: z2.string()
2104
+ });
2105
+ var QueryManualTestsRequestSchema = z2.object({
2106
+ sessionId: z2.string(),
2107
+ cardStatuses: z2.array(z2.string()).optional(),
2108
+ testStatuses: z2.array(z2.enum(["open", "approved", "rejected"])).optional()
2109
+ });
2110
+ var CreatePullRequestRequestSchema = CreatePRInputSchema.extend({ sessionId: z2.string() });
2111
+ var RequestFileUploadRequestSchema = z2.object({
2112
+ sessionId: z2.string(),
2113
+ fileName: z2.string().min(1).max(255),
2114
+ mimeType: z2.string().min(1).max(128),
2115
+ fileSize: z2.number().int().positive().max(MAX_FILE_SIZE_BYTES)
2116
+ });
2117
+ var ConfirmFileUploadRequestSchema = z2.object({
2118
+ sessionId: z2.string(),
2119
+ fileId: z2.string(),
2120
+ title: z2.string().max(500).optional()
2121
+ });
2122
+ var UpdateTaskStatusRequestSchema = z2.object({
2123
+ sessionId: z2.string(),
2124
+ status: z2.string(),
2125
+ force: z2.boolean().optional().default(false)
2126
+ });
2127
+ var StoreSessionIdRequestSchema = z2.object({
2128
+ sessionId: z2.string(),
2129
+ sdkSessionId: z2.string()
2130
+ });
2131
+ var SetManualTestsRequestSchema = z2.object({
2132
+ sessionId: z2.string(),
2133
+ items: z2.array(z2.object({ title: z2.string().min(1) })).min(1)
2134
+ });
2135
+ var EditManualTestRequestSchema = z2.object({
2136
+ sessionId: z2.string(),
2137
+ title: z2.string().min(1),
2138
+ newTitle: z2.string().min(1)
2139
+ });
2140
+ var RemoveManualTestRequestSchema = z2.object({
2141
+ sessionId: z2.string(),
2142
+ title: z2.string().min(1)
2143
+ });
2144
+ var ApproveManualTestRequestSchema = z2.object({
2145
+ sessionId: z2.string(),
2146
+ title: z2.string().min(1)
2147
+ });
2148
+ var RejectManualTestRequestSchema = z2.object({
2149
+ sessionId: z2.string(),
2150
+ title: z2.string().min(1),
2151
+ reason: z2.string().min(1).max(2e3)
2152
+ });
2153
+ var SessionStartRequestSchema = z2.object({
2154
+ sessionId: z2.string(),
2155
+ agentVersion: z2.string(),
2156
+ capabilities: z2.array(z2.string())
2157
+ });
2158
+ var SessionStopRequestSchema = z2.object({
2159
+ sessionId: z2.string(),
2160
+ reason: z2.string().optional()
2161
+ });
2162
+ var EndReviewSessionRequestSchema = z2.object({
2163
+ sessionId: z2.string(),
2164
+ reason: z2.enum(["approved", "changes_requested", "finished"]).optional()
2165
+ });
2166
+ var ConnectAgentRequestSchema = z2.object({
2167
+ sessionId: z2.string()
2168
+ });
2169
+ var ReportAgentStatusRequestSchema = z2.object({
2170
+ sessionId: z2.string(),
2171
+ status: z2.string(),
2035
2172
  /** Why the agent reports this status (e.g. "user_question" while an AskUserQuestion questionnaire is pending in the TUI). */
2036
- reason: z.string().optional(),
2173
+ reason: z2.string().optional(),
2037
2174
  /**
2038
2175
  * The pending question text, sent only alongside `reason: "user_question"`
2039
2176
  * so the server can surface it in the user-question notification body (and
2040
2177
  * thus the Attention feed) instead of a generic string. Optional: older
2041
2178
  * agents omit it and the server falls back to the generic wording.
2042
2179
  */
2043
- questionText: z.string().optional()
2044
- });
2045
- var NotifyAgentVersionRequestSchema = z.object({
2046
- sessionId: z.string(),
2047
- agentVersion: z.string()
2048
- });
2049
- var DiscoveredPortSchema = z.object({
2050
- port: z.number().int().min(1).max(65535),
2051
- label: z.string().min(1).max(64).optional(),
2052
- protocol: z.enum(["http", "tcp"]).optional(),
2053
- detectedAt: z.string()
2054
- });
2055
- var ReportDiscoveredPortsRequestSchema = z.object({
2056
- sessionId: z.string(),
2057
- ports: z.array(DiscoveredPortSchema).max(64)
2058
- });
2059
- var CreateSubtaskRequestSchema = z.object({
2060
- sessionId: z.string(),
2061
- title: z.string().min(1),
2062
- description: z.string().optional(),
2063
- plan: z.string().optional(),
2064
- storyPointValue: z.number().int().positive().optional(),
2065
- ordinal: z.number().int().nonnegative().optional(),
2066
- followParentStatus: z.boolean().optional(),
2180
+ questionText: z2.string().optional()
2181
+ });
2182
+ var NotifyAgentVersionRequestSchema = z2.object({
2183
+ sessionId: z2.string(),
2184
+ agentVersion: z2.string()
2185
+ });
2186
+ var DiscoveredPortSchema = z2.object({
2187
+ port: z2.number().int().min(1).max(65535),
2188
+ label: z2.string().min(1).max(64).optional(),
2189
+ protocol: z2.enum(["http", "tcp"]).optional(),
2190
+ detectedAt: z2.string()
2191
+ });
2192
+ var ReportDiscoveredPortsRequestSchema = z2.object({
2193
+ sessionId: z2.string(),
2194
+ ports: z2.array(DiscoveredPortSchema).max(64)
2195
+ });
2196
+ var CreateSubtaskRequestSchema = z2.object({
2197
+ sessionId: z2.string(),
2198
+ title: z2.string().min(1),
2199
+ description: z2.string().optional(),
2200
+ plan: z2.string().optional(),
2201
+ storyPointValue: z2.number().int().positive().optional(),
2202
+ ordinal: z2.number().int().nonnegative().optional(),
2203
+ followParentStatus: z2.boolean().optional(),
2067
2204
  /** Sibling subtask ids or slugs this subtask blocks on (explicit dependency
2068
2205
  * metadata — preferred over encoding order in plan text / ordinal). */
2069
- dependsOn: z.array(z.string().min(1)).max(32).optional()
2070
- });
2071
- var UpdateSubtaskRequestSchema = z.object({
2072
- sessionId: z.string(),
2073
- subtaskId: z.string(),
2074
- title: z.string().min(1).optional(),
2075
- description: z.string().optional(),
2076
- plan: z.string().optional(),
2206
+ dependsOn: z2.array(z2.string().min(1)).max(32).optional()
2207
+ });
2208
+ var UpdateSubtaskRequestSchema = z2.object({
2209
+ sessionId: z2.string(),
2210
+ subtaskId: z2.string(),
2211
+ title: z2.string().min(1).optional(),
2212
+ description: z2.string().optional(),
2213
+ plan: z2.string().optional(),
2077
2214
  /** Orchestration statuses only ("Planning" | "Open") — the pack parent's
2078
2215
  * sanctioned promotion path. Execution statuses stay with the build
2079
2216
  * pipeline / force_update_task_status. Enforced server-side. */
2080
- status: z.string().optional(),
2217
+ status: z2.string().optional(),
2081
2218
  /** Assign a project agent to the child — accepts the agent's id or exact
2082
2219
  * name; resolved against the parent task's project server-side. */
2083
- agentIdOrName: z.string().min(1).optional(),
2084
- storyPointValue: z.number().int().positive().optional(),
2085
- followParentStatus: z.boolean().optional(),
2220
+ agentIdOrName: z2.string().min(1).optional(),
2221
+ storyPointValue: z2.number().int().positive().optional(),
2222
+ followParentStatus: z2.boolean().optional(),
2086
2223
  /** Replace this subtask's dependency edges with these sibling ids/slugs.
2087
2224
  * Empty array clears all. Omit to leave dependencies unchanged. */
2088
- dependsOn: z.array(z.string().min(1)).max(32).optional()
2089
- });
2090
- var DeleteSubtaskRequestSchema = z.object({
2091
- sessionId: z.string(),
2092
- subtaskId: z.string()
2093
- });
2094
- var GetTaskPropertiesRequestSchema = z.object({
2095
- sessionId: z.string()
2096
- });
2097
- var GetCumulativeSpendingRequestSchema = z.object({
2098
- sessionId: z.string()
2099
- });
2100
- var ModelUsageEntrySchema = z.object({
2101
- model: z.string(),
2102
- inputTokens: z.number().nonnegative(),
2103
- outputTokens: z.number().nonnegative(),
2104
- cacheReadInputTokens: z.number().nonnegative(),
2105
- cacheCreationInputTokens: z.number().nonnegative(),
2106
- costUSD: z.number().nonnegative()
2107
- });
2108
- var GetCumulativeSpendingResponseSchema = z.object({
2109
- totalCostUsd: z.number().nonnegative(),
2110
- modelUsage: z.array(ModelUsageEntrySchema)
2111
- });
2112
- var UpdateTaskFieldsRequestSchema = z.object({
2113
- sessionId: z.string(),
2114
- plan: z.string().optional(),
2115
- description: z.string().optional()
2116
- });
2117
- var UpdateTaskPropertiesRequestSchema = z.object({
2118
- sessionId: z.string(),
2119
- title: z.string().optional(),
2120
- storyPointValue: z.number().int().positive().optional(),
2121
- tagIds: z.array(z.string()).optional(),
2122
- tagNames: z.array(z.string()).optional(),
2123
- githubPRUrl: z.string().url().optional(),
2124
- githubBranch: z.string().optional()
2125
- });
2126
- var ListIconsRequestSchema = z.object({
2127
- sessionId: z.string()
2128
- });
2129
- var GenerateTaskIconRequestSchema = z.object({
2130
- sessionId: z.string(),
2131
- prompt: z.string().min(1),
2132
- aspectRatio: z.string().optional()
2133
- });
2134
- var SearchFaIconsRequestSchema = z.object({
2135
- sessionId: z.string(),
2136
- query: z.string().min(1),
2137
- first: z.number().int().positive().optional()
2138
- });
2139
- var PickFaIconRequestSchema = z.object({
2140
- sessionId: z.string(),
2141
- fontAwesomeId: z.string().min(1),
2142
- fontAwesomeStyle: z.string().optional()
2143
- });
2144
- var CreateFollowUpTaskRequestSchema = z.object({
2145
- sessionId: z.string(),
2146
- title: z.string().min(1),
2147
- description: z.string().optional(),
2148
- plan: z.string().optional(),
2149
- storyPointValue: z.number().int().positive().optional()
2150
- });
2151
- var AddDependencyRequestSchema = z.object({
2152
- sessionId: z.string(),
2153
- dependsOnSlugOrId: z.string()
2154
- });
2155
- var RemoveDependencyRequestSchema = z.object({
2156
- sessionId: z.string(),
2157
- dependsOnSlugOrId: z.string()
2158
- });
2159
- var CreateSuggestionRequestSchema = z.object({
2160
- sessionId: z.string(),
2161
- title: z.string().min(1),
2162
- description: z.string().optional(),
2163
- tagNames: z.array(z.string()).optional()
2164
- });
2165
- var VoteSuggestionRequestSchema = z.object({
2166
- sessionId: z.string(),
2167
- suggestionId: z.string(),
2168
- value: z.union([z.literal(1), z.literal(-1)])
2169
- });
2170
- var TriggerIdentificationRequestSchema = z.object({
2171
- sessionId: z.string()
2172
- });
2173
- var SubmitCodeReviewResultRequestSchema = z.object({
2174
- sessionId: z.string(),
2175
- approved: z.boolean(),
2176
- content: z.string()
2177
- });
2178
- var StartChildCloudBuildRequestSchema = z.object({
2179
- sessionId: z.string(),
2180
- childTaskId: z.string()
2181
- });
2182
- var StopChildBuildRequestSchema = z.object({
2183
- sessionId: z.string(),
2184
- childTaskId: z.string()
2185
- });
2186
- var ApproveAndMergePRRequestSchema = z.object({
2187
- sessionId: z.string(),
2188
- childTaskId: z.string()
2189
- });
2190
- var PostChildChatMessageRequestSchema = z.object({
2191
- sessionId: z.string(),
2192
- childTaskId: z.string(),
2193
- message: z.string().min(1)
2194
- });
2195
- var UpdateChildStatusRequestSchema = z.object({
2196
- sessionId: z.string(),
2197
- childTaskId: z.string(),
2198
- status: z.string()
2199
- });
2200
- var GetAgentStatusRequestSchema = z.object({
2201
- taskId: z.string()
2202
- });
2203
- var GetUiCliHistoryRequestSchema = z.object({
2204
- taskId: z.string()
2205
- });
2206
- var GetActivePtySessionRequestSchema = z.object({
2207
- taskId: z.string()
2208
- });
2209
- var ListActivePtySessionsRequestSchema = z.object({
2210
- taskId: z.string()
2211
- });
2212
- var SendSoftStopRequestSchema = z.object({
2213
- taskId: z.string()
2214
- });
2215
- var StopTaskSessionRequestSchema = z.object({
2216
- taskId: z.string(),
2217
- sessionId: z.string()
2218
- });
2219
- var FlushTaskQueueRequestSchema = z.object({
2220
- taskId: z.string(),
2221
- softStop: z.boolean().optional()
2222
- });
2223
- var CancelTaskQueuedMessageRequestSchema = z.object({
2224
- taskId: z.string(),
2225
- messageId: z.string()
2226
- });
2227
- var FlushSingleQueuedMessageRequestSchema = z.object({
2228
- taskId: z.string(),
2229
- messageId: z.string(),
2230
- softStop: z.boolean().optional()
2231
- });
2232
- var AnswerAgentQuestionRequestSchema = z.object({
2233
- taskId: z.string(),
2234
- requestId: z.string(),
2235
- answers: z.record(z.string(), z.string())
2236
- });
2237
- var ClearAgentTodosRequestSchema = z.object({
2238
- taskId: z.string()
2239
- });
2240
- var AgentQuestionOptionSchema = z.object({
2241
- label: z.string(),
2242
- description: z.string(),
2243
- preview: z.string().optional()
2244
- });
2245
- var AgentQuestionSchema = z.object({
2246
- question: z.string(),
2247
- header: z.string(),
2248
- options: z.array(AgentQuestionOptionSchema),
2249
- multiSelect: z.boolean().optional()
2250
- });
2251
- var AskUserQuestionRequestSchema = z.object({
2252
- sessionId: z.string(),
2253
- question: z.string().min(1),
2254
- requestId: z.string().min(1),
2255
- questions: z.array(AgentQuestionSchema).min(1)
2256
- });
2257
- var AgentEventSchema = z.object({
2258
- type: z.string().min(1)
2259
- }).catchall(z.unknown());
2260
- var EmitAgentEventRequestSchema = z.object({
2261
- sessionId: z.string(),
2262
- events: z.array(AgentEventSchema).max(500)
2263
- });
2264
- var RefreshGithubTokenRequestSchema = z.object({
2265
- sessionId: z.string()
2266
- });
2267
- var ReportReviewSpawnFailureRequestSchema = z.object({
2268
- sessionId: z.string(),
2269
- reviewSessionId: z.string(),
2270
- error: z.string().max(2e3).optional()
2271
- });
2272
- var SpawnTaskSessionRequestSchema = z.object({
2273
- taskId: z.string(),
2274
- kind: z.enum(["tui", "shell"])
2275
- });
2276
- var SpawnTaskReviewRequestSchema = z.object({
2277
- taskId: z.string()
2278
- });
2279
- var ReportSessionSpawnFailureRequestSchema = z.object({
2280
- sessionId: z.string(),
2281
- spawnedSessionId: z.string(),
2282
- error: z.string().max(2e3).optional()
2283
- });
2284
- var RefreshGithubTokenResponseSchema = z.object({
2285
- token: z.string()
2225
+ dependsOn: z2.array(z2.string().min(1)).max(32).optional()
2286
2226
  });
2287
- var PTY_FRAME_MAX_CHARS = 256 * 1024;
2288
- var PTY_MAX_DIMENSION = 1e3;
2289
- var PtyOutputRequestSchema = z.object({
2290
- sessionId: z.string(),
2291
- data: z.string().max(PTY_FRAME_MAX_CHARS),
2292
- cols: z.number().int().positive().max(PTY_MAX_DIMENSION).optional(),
2293
- rows: z.number().int().positive().max(PTY_MAX_DIMENSION).optional()
2227
+ var DeleteSubtaskRequestSchema = z2.object({
2228
+ sessionId: z2.string(),
2229
+ subtaskId: z2.string()
2294
2230
  });
2295
- var PtyEndedRequestSchema = z.object({
2296
- sessionId: z.string()
2231
+ var GetTaskPropertiesRequestSchema = z2.object({
2232
+ sessionId: z2.string()
2297
2233
  });
2298
- var PtyInputRequestSchema = z.object({
2299
- sessionId: z.string(),
2300
- data: z.string().max(PTY_FRAME_MAX_CHARS)
2234
+ var UpdateTaskFieldsRequestSchema = z2.object({
2235
+ sessionId: z2.string(),
2236
+ plan: z2.string().optional(),
2237
+ description: z2.string().optional()
2301
2238
  });
2302
- var PtyResizeRequestSchema = z.object({
2303
- sessionId: z.string(),
2304
- cols: z.number().int().positive().max(PTY_MAX_DIMENSION),
2305
- rows: z.number().int().positive().max(PTY_MAX_DIMENSION)
2239
+ var UpdateTaskPropertiesRequestSchema = z2.object({
2240
+ sessionId: z2.string(),
2241
+ title: z2.string().optional(),
2242
+ storyPointValue: z2.number().int().positive().optional(),
2243
+ tagIds: z2.array(z2.string()).optional(),
2244
+ tagNames: z2.array(z2.string()).optional(),
2245
+ githubPRUrl: z2.string().url().optional(),
2246
+ githubBranch: z2.string().optional()
2306
2247
  });
2307
- var PtyAttachRequestSchema = z.object({
2308
- sessionId: z.string()
2248
+ var ListIconsRequestSchema = z2.object({
2249
+ sessionId: z2.string()
2309
2250
  });
2310
- var PtyChatEventPayloadSchema = z.discriminatedUnion("kind", [
2311
- z.object({
2312
- kind: z.literal("init"),
2313
- model: z.string().max(200),
2314
- claudeSessionId: z.string().max(100).optional()
2315
- }),
2316
- z.object({ kind: z.literal("user_text"), text: z.string().max(16384) }),
2317
- z.object({ kind: z.literal("assistant_text"), text: z.string().max(16384) }),
2318
- z.object({
2319
- kind: z.literal("tool_use"),
2320
- name: z.string().max(200),
2321
- // Compact preview: JSON.stringify(input) truncated agent-side.
2322
- input: z.string().max(2e3)
2323
- }),
2324
- z.object({ kind: z.literal("turn_end") })
2325
- ]);
2326
- var PtyChatEventRequestSchema = z.object({
2327
- sessionId: z.string(),
2328
- event: PtyChatEventPayloadSchema
2251
+ var GenerateTaskIconRequestSchema = z2.object({
2252
+ sessionId: z2.string(),
2253
+ prompt: z2.string().min(1),
2254
+ aspectRatio: z2.string().optional()
2329
2255
  });
2330
- var PtyChatAttachRequestSchema = z.object({
2331
- sessionId: z.string()
2256
+ var SearchFaIconsRequestSchema = z2.object({
2257
+ sessionId: z2.string(),
2258
+ query: z2.string().min(1),
2259
+ first: z2.number().int().positive().optional()
2332
2260
  });
2333
- var CreatePRResponseSchema = z.object({
2334
- prNumber: z.number().int().positive(),
2335
- prUrl: z.string().url()
2261
+ var PickFaIconRequestSchema = z2.object({
2262
+ sessionId: z2.string(),
2263
+ fontAwesomeId: z2.string().min(1),
2264
+ fontAwesomeStyle: z2.string().optional()
2336
2265
  });
2337
- var PostToChatResponseSchema = z.object({
2338
- messageId: z.string()
2266
+ var CreateFollowUpTaskRequestSchema = z2.object({
2267
+ sessionId: z2.string(),
2268
+ title: z2.string().min(1),
2269
+ description: z2.string().optional(),
2270
+ plan: z2.string().optional(),
2271
+ storyPointValue: z2.number().int().positive().optional()
2339
2272
  });
2340
- var UpdateTaskStatusResponseSchema = z.object({
2341
- taskId: z.string(),
2342
- status: z.string()
2273
+ var AddDependencyRequestSchema = z2.object({
2274
+ sessionId: z2.string(),
2275
+ dependsOnSlugOrId: z2.string()
2343
2276
  });
2344
- var StoreSessionIdResponseSchema = z.object({
2345
- success: z.boolean()
2277
+ var RemoveDependencyRequestSchema = z2.object({
2278
+ sessionId: z2.string(),
2279
+ dependsOnSlugOrId: z2.string()
2346
2280
  });
2347
- var HeartbeatResponseSchema = z.object({
2348
- acknowledged: z.boolean()
2281
+ var CreateSuggestionRequestSchema = z2.object({
2282
+ sessionId: z2.string(),
2283
+ title: z2.string().min(1),
2284
+ description: z2.string().optional(),
2285
+ tagNames: z2.array(z2.string()).optional()
2349
2286
  });
2350
- var SessionStartResponseSchema = z.object({
2351
- sessionId: z.string(),
2352
- startedAt: z.string()
2287
+ var VoteSuggestionRequestSchema = z2.object({
2288
+ sessionId: z2.string(),
2289
+ suggestionId: z2.string(),
2290
+ value: z2.union([z2.literal(1), z2.literal(-1)])
2353
2291
  });
2354
- var SessionStopResponseSchema = z.object({
2355
- sessionId: z.string(),
2356
- stoppedAt: z.string()
2292
+ var TriggerIdentificationRequestSchema = z2.object({
2293
+ sessionId: z2.string()
2357
2294
  });
2358
- var DeleteSubtaskResponseSchema = z.object({
2359
- deleted: z.boolean()
2295
+ var SubmitCodeReviewResultRequestSchema = z2.object({
2296
+ sessionId: z2.string(),
2297
+ approved: z2.boolean(),
2298
+ content: z2.string()
2360
2299
  });
2361
- var ListAccessibleProjectsRequestSchema = z2.object({
2362
- pageSize: z2.number().int().positive().max(100).optional().default(100)
2300
+ var CycleCodingAgentKeyRequestSchema = z2.object({
2301
+ sessionId: z2.string(),
2302
+ rateLimitType: z2.string(),
2303
+ resetsAt: z2.string().optional()
2363
2304
  });
2364
- var ListProjectTasksRequestSchema = z2.object({
2365
- projectId: z2.string(),
2366
- status: z2.string().optional(),
2367
- assigneeId: z2.string().optional(),
2368
- unassigned: z2.boolean().optional(),
2369
- limit: z2.number().int().positive().optional().default(50)
2370
- }).refine((p) => !(p.unassigned && p.assigneeId), {
2371
- message: "Pass either assigneeId or unassigned, not both"
2305
+ var StartChildCloudBuildRequestSchema = z2.object({
2306
+ sessionId: z2.string(),
2307
+ childTaskId: z2.string()
2372
2308
  });
2373
- var GetProjectTaskRequestSchema = z2.object({
2374
- projectId: z2.string(),
2375
- taskId: z2.string()
2309
+ var StopChildBuildRequestSchema = z2.object({
2310
+ sessionId: z2.string(),
2311
+ childTaskId: z2.string()
2376
2312
  });
2377
- var SearchProjectTasksRequestSchema = z2.object({
2378
- projectId: z2.string(),
2379
- tagNames: z2.array(z2.string()).optional(),
2380
- searchQuery: z2.string().optional(),
2381
- statusFilters: z2.array(z2.string()).optional(),
2382
- // Card types to include. Omitted/empty → defaults to ["task"] in the handler so
2383
- // search doesn't surface incidents/suggestions unless asked. Enum validation lives
2384
- // at the MCP tool layer (mirrors statusFilters).
2385
- typeFilters: z2.array(z2.string()).optional(),
2386
- assigneeId: z2.string().optional(),
2387
- unassigned: z2.boolean().optional(),
2388
- limit: z2.number().int().positive().optional().default(20)
2389
- }).refine((p) => !(p.unassigned && p.assigneeId), {
2390
- message: "Pass either assigneeId or unassigned, not both"
2313
+ var ApproveAndMergePRRequestSchema = z2.object({
2314
+ sessionId: z2.string(),
2315
+ childTaskId: z2.string()
2391
2316
  });
2392
- var ListProjectTagsRequestSchema = z2.object({
2393
- projectId: z2.string()
2317
+ var PostChildChatMessageRequestSchema = z2.object({
2318
+ sessionId: z2.string(),
2319
+ childTaskId: z2.string(),
2320
+ message: z2.string().min(1)
2394
2321
  });
2395
- var GetProjectSummaryRequestSchema = z2.object({
2396
- projectId: z2.string()
2322
+ var UpdateChildStatusRequestSchema = z2.object({
2323
+ sessionId: z2.string(),
2324
+ childTaskId: z2.string(),
2325
+ status: z2.string()
2397
2326
  });
2398
- var CreateProjectTaskRequestSchema = z2.object({
2399
- projectId: z2.string(),
2400
- title: z2.string().min(1),
2401
- description: z2.string().optional(),
2402
- plan: z2.string().optional(),
2403
- status: z2.string().optional(),
2404
- requestingUserId: z2.string().optional()
2327
+ var GetAgentStatusRequestSchema = z2.object({
2328
+ taskId: z2.string()
2405
2329
  });
2406
- var UpdateProjectTaskRequestSchema = z2.object({
2407
- projectId: z2.string(),
2408
- taskId: z2.string(),
2409
- title: z2.string().optional(),
2410
- description: z2.string().optional(),
2411
- plan: z2.string().optional(),
2412
- status: z2.string().optional(),
2413
- assignedUserId: z2.string().nullish(),
2414
- requestingUserId: z2.string().optional()
2330
+ var GetUiCliHistoryRequestSchema = z2.object({
2331
+ taskId: z2.string()
2415
2332
  });
2416
- var PostToProjectTaskChatRequestSchema = z2.object({
2417
- projectId: z2.string(),
2418
- taskId: z2.string(),
2419
- content: z2.string(),
2420
- requestingUserId: z2.string().optional()
2333
+ var GetActivePtySessionRequestSchema = z2.object({
2334
+ taskId: z2.string()
2421
2335
  });
2422
- var GetProjectTaskCliRequestSchema = z2.object({
2423
- projectId: z2.string(),
2424
- taskId: z2.string(),
2425
- limit: z2.number().int().positive().optional().default(50),
2426
- source: z2.string().optional()
2336
+ var ListActivePtySessionsRequestSchema = z2.object({
2337
+ taskId: z2.string()
2427
2338
  });
2428
- var GetProjectTaskSessionsRequestSchema = z2.object({
2429
- projectId: z2.string(),
2339
+ var SendSoftStopRequestSchema = z2.object({
2430
2340
  taskId: z2.string()
2431
2341
  });
2432
- var QueryProjectGcpLogsRequestSchema = z2.object({
2433
- projectId: z2.string(),
2434
- env: z2.enum(["prod", "dev", "claudespace"]).optional(),
2435
- severity: z2.enum(["DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "CRITICAL", "ALERT", "EMERGENCY"]).optional(),
2436
- services: z2.array(z2.string().min(1).max(200)).max(25).optional(),
2437
- sqlInstances: z2.array(z2.string().min(1).max(200)).max(25).optional(),
2438
- allServices: z2.boolean().optional(),
2439
- search: z2.string().max(256).optional(),
2440
- filter: z2.string().max(1e3).optional(),
2441
- startTime: z2.string().optional(),
2442
- endTime: z2.string().optional(),
2443
- limit: z2.number().int().min(1).max(200).optional().default(50),
2444
- pageToken: z2.string().max(4096).optional()
2445
- });
2446
- var StartProjectBuildRequestSchema = z2.object({
2447
- projectId: z2.string(),
2342
+ var StopTaskSessionRequestSchema = z2.object({
2448
2343
  taskId: z2.string(),
2449
- requestingUserId: z2.string().optional()
2344
+ sessionId: z2.string()
2450
2345
  });
2451
- var StopProjectBuildRequestSchema = z2.object({
2452
- projectId: z2.string(),
2346
+ var FlushTaskQueueRequestSchema = z2.object({
2453
2347
  taskId: z2.string(),
2454
- requestingUserId: z2.string().optional()
2348
+ softStop: z2.boolean().optional()
2455
2349
  });
2456
- var StartProjectWorkspaceRequestSchema = z2.object({
2457
- projectId: z2.string(),
2458
- requestingUserId: z2.string().optional()
2350
+ var CancelTaskQueuedMessageRequestSchema = z2.object({
2351
+ taskId: z2.string(),
2352
+ messageId: z2.string()
2459
2353
  });
2460
- var StopProjectWorkspaceRequestSchema = z2.object({
2461
- projectId: z2.string(),
2462
- destroy: z2.boolean().optional(),
2463
- requestingUserId: z2.string().optional()
2354
+ var FlushSingleQueuedMessageRequestSchema = z2.object({
2355
+ taskId: z2.string(),
2356
+ messageId: z2.string(),
2357
+ softStop: z2.boolean().optional()
2464
2358
  });
2465
- var ListMyLiveSessionsRequestSchema = z2.object({
2466
- projectId: z2.string(),
2467
- /** Admin-only: list another member's sessions instead of the caller's. */
2468
- targetUserId: z2.string().optional()
2359
+ var AnswerAgentQuestionRequestSchema = z2.object({
2360
+ taskId: z2.string(),
2361
+ requestId: z2.string(),
2362
+ answers: z2.record(z2.string(), z2.string())
2469
2363
  });
2470
- var ListProjectSessionGroupsRequestSchema = z2.object({
2471
- projectId: z2.string()
2364
+ var ClearAgentTodosRequestSchema = z2.object({
2365
+ taskId: z2.string()
2472
2366
  });
2473
- var GetProjectAvailableTuisRequestSchema = z2.object({
2474
- projectId: z2.string()
2367
+ var AgentQuestionOptionSchema = z2.object({
2368
+ label: z2.string(),
2369
+ description: z2.string(),
2370
+ preview: z2.string().optional()
2475
2371
  });
2476
- var StartAdhocSessionRequestSchema = z2.object({
2477
- projectId: z2.string(),
2478
- label: z2.string().max(200).optional(),
2479
- /** Coding-agent key to launch under — validated pick-time (ownership + TUI availability) in the handler. */
2480
- codingAgentKeyId: z2.string().optional(),
2481
- /**
2482
- * Session role. Constrained: other task-less modes fall through to the pm
2483
- * runner in the pod entrypoint, and "review" would crash without a task.
2484
- */
2485
- mode: z2.enum(["adhoc", "pm"]).optional(),
2486
- /** Base branch to check out (defaults to the project's dev branch). */
2487
- branch: z2.string().max(300).optional(),
2488
- requestingUserId: z2.string().optional()
2489
- });
2490
- var StopAdhocSessionRequestSchema = z2.object({
2491
- projectId: z2.string(),
2492
- workspaceId: z2.string(),
2493
- destroy: z2.boolean().optional(),
2494
- requestingUserId: z2.string().optional()
2495
- });
2496
- var ResumeAdhocSessionRequestSchema = z2.object({
2497
- projectId: z2.string(),
2498
- workspaceId: z2.string(),
2499
- requestingUserId: z2.string().optional()
2500
- });
2501
- var CreateProjectReleaseRequestSchema = z2.object({
2502
- projectId: z2.string(),
2503
- taskIds: z2.array(z2.string()).optional(),
2504
- requestingUserId: z2.string().optional()
2505
- });
2506
- var ApproveProjectMergePRRequestSchema = z2.object({
2507
- projectId: z2.string(),
2508
- childTaskId: z2.string(),
2509
- requestingUserId: z2.string().optional()
2372
+ var AgentQuestionSchema = z2.object({
2373
+ question: z2.string(),
2374
+ header: z2.string(),
2375
+ options: z2.array(AgentQuestionOptionSchema),
2376
+ multiSelect: z2.boolean().optional()
2510
2377
  });
2511
- var ListProjectSubtasksRequestSchema = z2.object({
2512
- projectId: z2.string(),
2513
- taskId: z2.string()
2378
+ var AskUserQuestionRequestSchema = z2.object({
2379
+ sessionId: z2.string(),
2380
+ question: z2.string().min(1),
2381
+ requestId: z2.string().min(1),
2382
+ questions: z2.array(AgentQuestionSchema).min(1)
2514
2383
  });
2515
- var CreateProjectSubtaskRequestSchema = z2.object({
2516
- projectId: z2.string(),
2517
- parentTaskId: z2.string(),
2518
- title: z2.string().min(1),
2519
- description: z2.string().optional(),
2520
- plan: z2.string().optional(),
2521
- ordinal: z2.number().int().nonnegative().optional(),
2522
- storyPointValue: z2.number().int().positive().optional(),
2523
- followParentStatus: z2.boolean().optional(),
2524
- /** Sibling subtask ids or slugs this subtask blocks on (explicit dependency
2525
- * metadata — preferred over encoding order in plan text / ordinal). */
2526
- dependsOn: z2.array(z2.string().min(1)).max(32).optional(),
2527
- requestingUserId: z2.string().optional()
2384
+ var EmitAgentEventRequestSchema = z2.object({
2385
+ sessionId: z2.string(),
2386
+ events: z2.array(AgentEventSchema).max(500)
2528
2387
  });
2529
- var UpdateProjectSubtaskRequestSchema = z2.object({
2530
- projectId: z2.string(),
2531
- subtaskId: z2.string(),
2532
- title: z2.string().optional(),
2533
- description: z2.string().optional(),
2534
- plan: z2.string().optional(),
2535
- status: z2.string().optional(),
2536
- ordinal: z2.number().int().nonnegative().optional(),
2537
- storyPointValue: z2.number().int().positive().optional(),
2538
- followParentStatus: z2.boolean().optional(),
2539
- requestingUserId: z2.string().optional()
2388
+ var RefreshGithubTokenRequestSchema = z2.object({
2389
+ sessionId: z2.string()
2540
2390
  });
2541
- var DeleteProjectSubtaskRequestSchema = z2.object({
2542
- projectId: z2.string(),
2543
- subtaskId: z2.string(),
2544
- requestingUserId: z2.string().optional()
2391
+ var ReportReviewSpawnFailureRequestSchema = z2.object({
2392
+ sessionId: z2.string(),
2393
+ reviewSessionId: z2.string(),
2394
+ error: z2.string().max(2e3).optional()
2545
2395
  });
2546
- var GetProjectTaskChatRequestSchema = z2.object({
2547
- projectId: z2.string(),
2396
+ var SpawnTaskSessionRequestSchema = z2.object({
2548
2397
  taskId: z2.string(),
2549
- limit: z2.number().int().positive().optional().default(20)
2398
+ kind: z2.enum(["tui", "shell"])
2550
2399
  });
2551
- var AddProjectTaskDependencyRequestSchema = z2.object({
2552
- projectId: z2.string(),
2553
- taskId: z2.string(),
2554
- dependsOnSlugOrId: z2.string(),
2555
- requestingUserId: z2.string().optional()
2400
+ var SpawnTaskReviewRequestSchema = z2.object({
2401
+ taskId: z2.string()
2556
2402
  });
2557
- var RemoveProjectTaskDependencyRequestSchema = z2.object({
2558
- projectId: z2.string(),
2559
- taskId: z2.string(),
2560
- dependsOnSlugOrId: z2.string(),
2561
- requestingUserId: z2.string().optional()
2403
+ var ReportSessionSpawnFailureRequestSchema = z2.object({
2404
+ sessionId: z2.string(),
2405
+ spawnedSessionId: z2.string(),
2406
+ error: z2.string().max(2e3).optional()
2562
2407
  });
2563
- var VoteProjectSuggestionRequestSchema = z2.object({
2564
- projectId: z2.string(),
2565
- suggestionId: z2.string(),
2566
- value: z2.union([z2.literal(1), z2.literal(-1)]),
2567
- requestingUserId: z2.string().optional()
2408
+ var RefreshGithubTokenResponseSchema = z2.object({
2409
+ token: z2.string()
2568
2410
  });
2569
- var GetProjectTaskDependenciesRequestSchema = z2.object({
2570
- projectId: z2.string(),
2571
- taskId: z2.string()
2411
+ var PTY_FRAME_MAX_CHARS = 256 * 1024;
2412
+ var PTY_MAX_DIMENSION = 1e3;
2413
+ var PtyOutputRequestSchema = z2.object({
2414
+ sessionId: z2.string(),
2415
+ data: z2.string().max(PTY_FRAME_MAX_CHARS),
2416
+ cols: z2.number().int().positive().max(PTY_MAX_DIMENSION).optional(),
2417
+ rows: z2.number().int().positive().max(PTY_MAX_DIMENSION).optional()
2418
+ });
2419
+ var PtyEndedRequestSchema = z2.object({
2420
+ sessionId: z2.string()
2421
+ });
2422
+ var PtyInputRequestSchema = z2.object({
2423
+ sessionId: z2.string(),
2424
+ data: z2.string().max(PTY_FRAME_MAX_CHARS)
2425
+ });
2426
+ var PtyResizeRequestSchema = z2.object({
2427
+ sessionId: z2.string(),
2428
+ cols: z2.number().int().positive().max(PTY_MAX_DIMENSION),
2429
+ rows: z2.number().int().positive().max(PTY_MAX_DIMENSION)
2430
+ });
2431
+ var PtyAttachRequestSchema = z2.object({
2432
+ sessionId: z2.string()
2433
+ });
2434
+ var PtyChatEventPayloadSchema = z2.discriminatedUnion("kind", [
2435
+ z2.object({
2436
+ kind: z2.literal("init"),
2437
+ model: z2.string().max(200),
2438
+ claudeSessionId: z2.string().max(100).optional()
2439
+ }),
2440
+ z2.object({ kind: z2.literal("user_text"), text: z2.string().max(16384) }),
2441
+ z2.object({ kind: z2.literal("assistant_text"), text: z2.string().max(16384) }),
2442
+ z2.object({
2443
+ kind: z2.literal("tool_use"),
2444
+ name: z2.string().max(200),
2445
+ // Compact preview: JSON.stringify(input) truncated agent-side.
2446
+ input: z2.string().max(2e3)
2447
+ }),
2448
+ z2.object({ kind: z2.literal("turn_end") })
2449
+ ]);
2450
+ var PtyChatEventRequestSchema = z2.object({
2451
+ sessionId: z2.string(),
2452
+ event: PtyChatEventPayloadSchema
2572
2453
  });
2573
- var ListProjectTaskFilesRequestSchema = z2.object({
2574
- projectId: z2.string(),
2575
- taskId: z2.string()
2454
+ var PtyChatAttachRequestSchema = z2.object({
2455
+ sessionId: z2.string()
2576
2456
  });
2577
- var GetProjectAttachmentRequestSchema = z2.object({
2578
- projectId: z2.string(),
2579
- taskId: z2.string(),
2580
- fileId: z2.string(),
2581
- /** Byte offset into text content (paging large logs/JSON). Default 0. */
2582
- offset: z2.number().int().nonnegative().optional(),
2583
- /** Max bytes of text content to return from `offset`. Server default applies. */
2584
- maxBytes: z2.number().int().positive().optional()
2457
+ var CreatePRResponseSchema = z2.object({
2458
+ prNumber: z2.number().int().positive(),
2459
+ prUrl: z2.string().url()
2585
2460
  });
2586
- var RequestProjectFileUploadRequestSchema = z2.object({
2587
- projectId: z2.string(),
2588
- taskId: z2.string(),
2589
- fileName: z2.string().min(1).max(255),
2590
- mimeType: z2.string().min(1).max(128),
2591
- fileSize: z2.number().int().positive().max(MAX_FILE_SIZE_BYTES),
2592
- requestingUserId: z2.string().optional()
2461
+ var PostToChatResponseSchema = z2.object({
2462
+ messageId: z2.string()
2593
2463
  });
2594
- var ConfirmProjectFileUploadRequestSchema = z2.object({
2595
- projectId: z2.string(),
2464
+ var UpdateTaskStatusResponseSchema = z2.object({
2596
2465
  taskId: z2.string(),
2597
- fileId: z2.string(),
2598
- /** When set, the attachment is also posted to the task chat with this text. */
2599
- comment: z2.string().max(2e3).optional(),
2600
- requestingUserId: z2.string().optional()
2466
+ status: z2.string()
2601
2467
  });
2602
- var CreateProjectPullRequestRequestSchema = z2.object({
2603
- projectId: z2.string(),
2604
- taskId: z2.string(),
2605
- title: z2.string().min(1),
2606
- body: z2.string(),
2607
- head: z2.string().optional(),
2608
- base: z2.string().optional(),
2609
- requestingUserId: z2.string().optional()
2468
+ var StoreSessionIdResponseSchema = z2.object({
2469
+ success: z2.boolean()
2610
2470
  });
2611
- var ListProjectMembersRequestSchema = z2.object({
2612
- projectId: z2.string()
2471
+ var HeartbeatResponseSchema = z2.object({
2472
+ acknowledged: z2.boolean()
2613
2473
  });
2614
- var AddProjectTaskReviewerRequestSchema = z2.object({
2615
- projectId: z2.string(),
2616
- taskId: z2.string(),
2617
- userId: z2.string(),
2618
- requestingUserId: z2.string().optional()
2474
+ var SessionStartResponseSchema = z2.object({
2475
+ sessionId: z2.string(),
2476
+ startedAt: z2.string()
2619
2477
  });
2620
- var RemoveProjectTaskReviewerRequestSchema = z2.object({
2621
- projectId: z2.string(),
2622
- taskId: z2.string(),
2623
- userId: z2.string(),
2624
- requestingUserId: z2.string().optional()
2478
+ var SessionStopResponseSchema = z2.object({
2479
+ sessionId: z2.string(),
2480
+ stoppedAt: z2.string()
2625
2481
  });
2626
- var ListProjectManualTestsRequestSchema = z2.object({
2627
- projectId: z2.string(),
2628
- taskId: z2.string()
2482
+ var DeleteSubtaskResponseSchema = z2.object({
2483
+ deleted: z2.boolean()
2629
2484
  });
2630
- var QueryProjectManualTestsRequestSchema = z2.object({
2631
- projectId: z2.string(),
2632
- cardStatuses: z2.array(z2.string()).optional(),
2633
- testStatuses: z2.array(z2.enum(["open", "approved", "rejected"])).optional()
2485
+ var ListAccessibleProjectsRequestSchema = z3.object({
2486
+ pageSize: z3.number().int().positive().max(100).optional().default(100)
2634
2487
  });
2635
- var SetProjectManualTestsRequestSchema = z2.object({
2636
- projectId: z2.string(),
2637
- taskId: z2.string(),
2638
- items: z2.array(z2.object({ title: z2.string().min(1) })).min(1),
2639
- requestingUserId: z2.string().optional()
2488
+ var ListProjectTasksRequestSchema = z3.object({
2489
+ projectId: z3.string(),
2490
+ status: z3.string().optional(),
2491
+ assigneeId: z3.string().optional(),
2492
+ unassigned: z3.boolean().optional(),
2493
+ limit: z3.number().int().positive().optional().default(50)
2494
+ }).refine((p) => !(p.unassigned && p.assigneeId), {
2495
+ message: "Pass either assigneeId or unassigned, not both"
2640
2496
  });
2641
- var EditProjectManualTestRequestSchema = z2.object({
2642
- projectId: z2.string(),
2643
- taskId: z2.string(),
2644
- title: z2.string().min(1),
2645
- newTitle: z2.string().min(1),
2646
- requestingUserId: z2.string().optional()
2497
+ var GetProjectTaskRequestSchema = z3.object({
2498
+ projectId: z3.string(),
2499
+ taskId: z3.string()
2647
2500
  });
2648
- var RemoveProjectManualTestRequestSchema = z2.object({
2649
- projectId: z2.string(),
2650
- taskId: z2.string(),
2651
- title: z2.string().min(1),
2652
- requestingUserId: z2.string().optional()
2501
+ var SearchProjectTasksRequestSchema = z3.object({
2502
+ projectId: z3.string(),
2503
+ tagNames: z3.array(z3.string()).optional(),
2504
+ searchQuery: z3.string().optional(),
2505
+ statusFilters: z3.array(z3.string()).optional(),
2506
+ // Card types to include. Omitted/empty → defaults to ["task"] in the handler so
2507
+ // search doesn't surface incidents/suggestions unless asked. Enum validation lives
2508
+ // at the MCP tool layer (mirrors statusFilters).
2509
+ typeFilters: z3.array(z3.string()).optional(),
2510
+ assigneeId: z3.string().optional(),
2511
+ unassigned: z3.boolean().optional(),
2512
+ limit: z3.number().int().positive().optional().default(20)
2513
+ }).refine((p) => !(p.unassigned && p.assigneeId), {
2514
+ message: "Pass either assigneeId or unassigned, not both"
2653
2515
  });
2654
- var ApproveProjectManualTestRequestSchema = z2.object({
2655
- projectId: z2.string(),
2656
- taskId: z2.string(),
2657
- title: z2.string().min(1),
2658
- requestingUserId: z2.string().optional()
2516
+ var ListProjectTagsRequestSchema = z3.object({
2517
+ projectId: z3.string()
2518
+ });
2519
+ var GetProjectSummaryRequestSchema = z3.object({
2520
+ projectId: z3.string()
2521
+ });
2522
+ var CreateProjectTaskRequestSchema = z3.object({
2523
+ projectId: z3.string(),
2524
+ title: z3.string().min(1),
2525
+ description: z3.string().optional(),
2526
+ plan: z3.string().optional(),
2527
+ status: z3.string().optional(),
2528
+ requestingUserId: z3.string().optional()
2529
+ });
2530
+ var UpdateProjectTaskRequestSchema = z3.object({
2531
+ projectId: z3.string(),
2532
+ taskId: z3.string(),
2533
+ title: z3.string().optional(),
2534
+ description: z3.string().optional(),
2535
+ plan: z3.string().optional(),
2536
+ status: z3.string().optional(),
2537
+ assignedUserId: z3.string().nullish(),
2538
+ requestingUserId: z3.string().optional()
2539
+ });
2540
+ var PostToProjectTaskChatRequestSchema = z3.object({
2541
+ projectId: z3.string(),
2542
+ taskId: z3.string(),
2543
+ content: z3.string(),
2544
+ requestingUserId: z3.string().optional()
2545
+ });
2546
+ var GetProjectTaskCliRequestSchema = z3.object({
2547
+ projectId: z3.string(),
2548
+ taskId: z3.string(),
2549
+ limit: z3.number().int().positive().optional().default(50),
2550
+ source: z3.string().optional()
2551
+ });
2552
+ var GetProjectTaskSessionsRequestSchema = z3.object({
2553
+ projectId: z3.string(),
2554
+ taskId: z3.string()
2555
+ });
2556
+ var QueryProjectGcpLogsRequestSchema = z3.object({
2557
+ projectId: z3.string(),
2558
+ env: z3.enum(["prod", "dev", "claudespace"]).optional(),
2559
+ severity: z3.enum(["DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "CRITICAL", "ALERT", "EMERGENCY"]).optional(),
2560
+ services: z3.array(z3.string().min(1).max(200)).max(25).optional(),
2561
+ sqlInstances: z3.array(z3.string().min(1).max(200)).max(25).optional(),
2562
+ allServices: z3.boolean().optional(),
2563
+ search: z3.string().max(256).optional(),
2564
+ filter: z3.string().max(1e3).optional(),
2565
+ startTime: z3.string().optional(),
2566
+ endTime: z3.string().optional(),
2567
+ limit: z3.number().int().min(1).max(200).optional().default(50),
2568
+ pageToken: z3.string().max(4096).optional()
2569
+ });
2570
+ var StartProjectBuildRequestSchema = z3.object({
2571
+ projectId: z3.string(),
2572
+ taskId: z3.string(),
2573
+ requestingUserId: z3.string().optional()
2574
+ });
2575
+ var StopProjectBuildRequestSchema = z3.object({
2576
+ projectId: z3.string(),
2577
+ taskId: z3.string(),
2578
+ requestingUserId: z3.string().optional()
2579
+ });
2580
+ var StartProjectWorkspaceRequestSchema = z3.object({
2581
+ projectId: z3.string(),
2582
+ requestingUserId: z3.string().optional()
2583
+ });
2584
+ var StopProjectWorkspaceRequestSchema = z3.object({
2585
+ projectId: z3.string(),
2586
+ destroy: z3.boolean().optional(),
2587
+ requestingUserId: z3.string().optional()
2588
+ });
2589
+ var ListMyLiveSessionsRequestSchema = z3.object({
2590
+ projectId: z3.string(),
2591
+ /** Admin-only: list another member's sessions instead of the caller's. */
2592
+ targetUserId: z3.string().optional()
2659
2593
  });
2660
- var RejectProjectManualTestRequestSchema = z2.object({
2661
- projectId: z2.string(),
2662
- taskId: z2.string(),
2663
- title: z2.string().min(1),
2664
- reason: z2.string().min(1).max(2e3),
2665
- requestingUserId: z2.string().optional()
2594
+ var ListProjectSessionGroupsRequestSchema = z3.object({
2595
+ projectId: z3.string()
2666
2596
  });
2667
- var CreateProjectSuggestionRequestSchema = z2.object({
2668
- projectId: z2.string(),
2669
- title: z2.string().min(1),
2670
- description: z2.string().optional(),
2671
- tagNames: z2.array(z2.string()).optional(),
2672
- requestingUserId: z2.string().optional()
2597
+ var GetProjectAvailableTuisRequestSchema = z3.object({
2598
+ projectId: z3.string()
2599
+ });
2600
+ var StartAdhocSessionRequestSchema = z3.object({
2601
+ projectId: z3.string(),
2602
+ label: z3.string().max(200).optional(),
2603
+ /** Coding-agent key to launch under — validated pick-time (ownership + TUI availability) in the handler. */
2604
+ codingAgentKeyId: z3.string().optional(),
2605
+ /**
2606
+ * Session role. Constrained: other task-less modes fall through to the pm
2607
+ * runner in the pod entrypoint, and "review" would crash without a task.
2608
+ */
2609
+ mode: z3.enum(["adhoc", "pm"]).optional(),
2610
+ /** Base branch to check out (defaults to the project's dev branch). */
2611
+ branch: z3.string().max(300).optional(),
2612
+ requestingUserId: z3.string().optional()
2613
+ });
2614
+ var StopAdhocSessionRequestSchema = z3.object({
2615
+ projectId: z3.string(),
2616
+ workspaceId: z3.string(),
2617
+ destroy: z3.boolean().optional(),
2618
+ requestingUserId: z3.string().optional()
2619
+ });
2620
+ var ResumeAdhocSessionRequestSchema = z3.object({
2621
+ projectId: z3.string(),
2622
+ workspaceId: z3.string(),
2623
+ requestingUserId: z3.string().optional()
2624
+ });
2625
+ var CreateProjectReleaseRequestSchema = z3.object({
2626
+ projectId: z3.string(),
2627
+ taskIds: z3.array(z3.string()).optional(),
2628
+ requestingUserId: z3.string().optional()
2629
+ });
2630
+ var ApproveProjectMergePRRequestSchema = z3.object({
2631
+ projectId: z3.string(),
2632
+ childTaskId: z3.string(),
2633
+ requestingUserId: z3.string().optional()
2634
+ });
2635
+ var ListProjectSubtasksRequestSchema = z3.object({
2636
+ projectId: z3.string(),
2637
+ taskId: z3.string()
2638
+ });
2639
+ var CreateProjectSubtaskRequestSchema = z3.object({
2640
+ projectId: z3.string(),
2641
+ parentTaskId: z3.string(),
2642
+ title: z3.string().min(1),
2643
+ description: z3.string().optional(),
2644
+ plan: z3.string().optional(),
2645
+ ordinal: z3.number().int().nonnegative().optional(),
2646
+ storyPointValue: z3.number().int().positive().optional(),
2647
+ followParentStatus: z3.boolean().optional(),
2648
+ /** Sibling subtask ids or slugs this subtask blocks on (explicit dependency
2649
+ * metadata — preferred over encoding order in plan text / ordinal). */
2650
+ dependsOn: z3.array(z3.string().min(1)).max(32).optional(),
2651
+ requestingUserId: z3.string().optional()
2652
+ });
2653
+ var UpdateProjectSubtaskRequestSchema = z3.object({
2654
+ projectId: z3.string(),
2655
+ subtaskId: z3.string(),
2656
+ title: z3.string().optional(),
2657
+ description: z3.string().optional(),
2658
+ plan: z3.string().optional(),
2659
+ status: z3.string().optional(),
2660
+ ordinal: z3.number().int().nonnegative().optional(),
2661
+ storyPointValue: z3.number().int().positive().optional(),
2662
+ followParentStatus: z3.boolean().optional(),
2663
+ requestingUserId: z3.string().optional()
2664
+ });
2665
+ var DeleteProjectSubtaskRequestSchema = z3.object({
2666
+ projectId: z3.string(),
2667
+ subtaskId: z3.string(),
2668
+ requestingUserId: z3.string().optional()
2669
+ });
2670
+ var GetProjectTaskChatRequestSchema = z3.object({
2671
+ projectId: z3.string(),
2672
+ taskId: z3.string(),
2673
+ limit: z3.number().int().positive().optional().default(20)
2674
+ });
2675
+ var AddProjectTaskDependencyRequestSchema = z3.object({
2676
+ projectId: z3.string(),
2677
+ taskId: z3.string(),
2678
+ dependsOnSlugOrId: z3.string(),
2679
+ requestingUserId: z3.string().optional()
2680
+ });
2681
+ var RemoveProjectTaskDependencyRequestSchema = z3.object({
2682
+ projectId: z3.string(),
2683
+ taskId: z3.string(),
2684
+ dependsOnSlugOrId: z3.string(),
2685
+ requestingUserId: z3.string().optional()
2686
+ });
2687
+ var VoteProjectSuggestionRequestSchema = z3.object({
2688
+ projectId: z3.string(),
2689
+ suggestionId: z3.string(),
2690
+ value: z3.union([z3.literal(1), z3.literal(-1)]),
2691
+ requestingUserId: z3.string().optional()
2692
+ });
2693
+ var GetProjectTaskDependenciesRequestSchema = z3.object({
2694
+ projectId: z3.string(),
2695
+ taskId: z3.string()
2696
+ });
2697
+ var ListProjectTaskFilesRequestSchema = z3.object({
2698
+ projectId: z3.string(),
2699
+ taskId: z3.string()
2700
+ });
2701
+ var GetProjectAttachmentRequestSchema = z3.object({
2702
+ projectId: z3.string(),
2703
+ taskId: z3.string(),
2704
+ fileId: z3.string(),
2705
+ /** Byte offset into text content (paging large logs/JSON). Default 0. */
2706
+ offset: z3.number().int().nonnegative().optional(),
2707
+ /** Max bytes of text content to return from `offset`. Server default applies. */
2708
+ maxBytes: z3.number().int().positive().optional()
2709
+ });
2710
+ var RequestProjectFileUploadRequestSchema = z3.object({
2711
+ projectId: z3.string(),
2712
+ taskId: z3.string(),
2713
+ fileName: z3.string().min(1).max(255),
2714
+ mimeType: z3.string().min(1).max(128),
2715
+ fileSize: z3.number().int().positive().max(MAX_FILE_SIZE_BYTES),
2716
+ requestingUserId: z3.string().optional()
2717
+ });
2718
+ var ConfirmProjectFileUploadRequestSchema = z3.object({
2719
+ projectId: z3.string(),
2720
+ taskId: z3.string(),
2721
+ fileId: z3.string(),
2722
+ /** When set, the attachment is also posted to the task chat with this text. */
2723
+ comment: z3.string().max(2e3).optional(),
2724
+ requestingUserId: z3.string().optional()
2725
+ });
2726
+ var CreateProjectPullRequestRequestSchema = z3.object({
2727
+ projectId: z3.string(),
2728
+ taskId: z3.string(),
2729
+ title: z3.string().min(1),
2730
+ body: z3.string(),
2731
+ head: z3.string().optional(),
2732
+ base: z3.string().optional(),
2733
+ requestingUserId: z3.string().optional()
2734
+ });
2735
+ var ListProjectMembersRequestSchema = z3.object({
2736
+ projectId: z3.string()
2737
+ });
2738
+ var AddProjectTaskReviewerRequestSchema = z3.object({
2739
+ projectId: z3.string(),
2740
+ taskId: z3.string(),
2741
+ userId: z3.string(),
2742
+ requestingUserId: z3.string().optional()
2743
+ });
2744
+ var RemoveProjectTaskReviewerRequestSchema = z3.object({
2745
+ projectId: z3.string(),
2746
+ taskId: z3.string(),
2747
+ userId: z3.string(),
2748
+ requestingUserId: z3.string().optional()
2749
+ });
2750
+ var ListProjectManualTestsRequestSchema = z3.object({
2751
+ projectId: z3.string(),
2752
+ taskId: z3.string()
2753
+ });
2754
+ var QueryProjectManualTestsRequestSchema = z3.object({
2755
+ projectId: z3.string(),
2756
+ cardStatuses: z3.array(z3.string()).optional(),
2757
+ testStatuses: z3.array(z3.enum(["open", "approved", "rejected"])).optional()
2758
+ });
2759
+ var SetProjectManualTestsRequestSchema = z3.object({
2760
+ projectId: z3.string(),
2761
+ taskId: z3.string(),
2762
+ items: z3.array(z3.object({ title: z3.string().min(1) })).min(1),
2763
+ requestingUserId: z3.string().optional()
2764
+ });
2765
+ var EditProjectManualTestRequestSchema = z3.object({
2766
+ projectId: z3.string(),
2767
+ taskId: z3.string(),
2768
+ title: z3.string().min(1),
2769
+ newTitle: z3.string().min(1),
2770
+ requestingUserId: z3.string().optional()
2771
+ });
2772
+ var RemoveProjectManualTestRequestSchema = z3.object({
2773
+ projectId: z3.string(),
2774
+ taskId: z3.string(),
2775
+ title: z3.string().min(1),
2776
+ requestingUserId: z3.string().optional()
2777
+ });
2778
+ var ApproveProjectManualTestRequestSchema = z3.object({
2779
+ projectId: z3.string(),
2780
+ taskId: z3.string(),
2781
+ title: z3.string().min(1),
2782
+ requestingUserId: z3.string().optional()
2783
+ });
2784
+ var RejectProjectManualTestRequestSchema = z3.object({
2785
+ projectId: z3.string(),
2786
+ taskId: z3.string(),
2787
+ title: z3.string().min(1),
2788
+ reason: z3.string().min(1).max(2e3),
2789
+ requestingUserId: z3.string().optional()
2790
+ });
2791
+ var CreateProjectSuggestionRequestSchema = z3.object({
2792
+ projectId: z3.string(),
2793
+ title: z3.string().min(1),
2794
+ description: z3.string().optional(),
2795
+ tagNames: z3.array(z3.string()).optional(),
2796
+ requestingUserId: z3.string().optional()
2673
2797
  });
2674
2798
  var AGENT_STATUS_REASON_USER_QUESTION = "user_question";
2675
2799
  var TASK_CHAT_HISTORY_LIMIT = 20;
@@ -2726,7 +2850,7 @@ var ModeController = class {
2726
2850
  }
2727
2851
  get isBuildCapable() {
2728
2852
  const m = this.effectiveMode;
2729
- return m === "building" || m === "review" || m === "auto" && this._hasExitedPlanMode;
2853
+ return m === "building" || m === "review" || m === "chat" || m === "auto" && this._hasExitedPlanMode;
2730
2854
  }
2731
2855
  /**
2732
2856
  * Apply authoritative mode from the server's task context.
@@ -3375,6 +3499,36 @@ var JsonlTailer = class {
3375
3499
  }
3376
3500
  };
3377
3501
 
3502
+ // src/harness/pty/limit-banner.ts
3503
+ var BANNER_RE = /you'?(?:ve| have) (?:hit|reached) your ([\w-]+ )?(?:usage )?limit/i;
3504
+ var RESET_RE = /resets?\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*\(UTC\)/i;
3505
+ function nextUtcOccurrenceSeconds(hour12, minute, meridiem, nowMs) {
3506
+ let hour = hour12 % 12;
3507
+ if (meridiem.toLowerCase() === "pm") hour += 12;
3508
+ const candidate = new Date(nowMs);
3509
+ candidate.setUTCHours(hour, minute, 0, 0);
3510
+ if (candidate.getTime() <= nowMs) candidate.setUTCDate(candidate.getUTCDate() + 1);
3511
+ return Math.floor(candidate.getTime() / 1e3);
3512
+ }
3513
+ function matchUsageLimitBanner(text, now = Date.now()) {
3514
+ const banner = BANNER_RE.exec(text);
3515
+ if (!banner) return null;
3516
+ const qualifier = banner[1]?.trim().toLowerCase();
3517
+ const rateLimitType = qualifier === "weekly" ? "seven_day" : "five_hour";
3518
+ const reset = RESET_RE.exec(text);
3519
+ return {
3520
+ rateLimitType,
3521
+ ...reset ? {
3522
+ resetsAtEpochSeconds: nextUtcOccurrenceSeconds(
3523
+ Number(reset[1]),
3524
+ reset[2] ? Number(reset[2]) : 0,
3525
+ reset[3],
3526
+ now
3527
+ )
3528
+ } : {}
3529
+ };
3530
+ }
3531
+
3378
3532
  // src/harness/pty/chat-record-mapper.ts
3379
3533
  var TEXT_MAX = 16e3;
3380
3534
  var TOOL_INPUT_MAX = 1900;
@@ -3768,7 +3922,7 @@ var PtyOutputCoalescer = class {
3768
3922
 
3769
3923
  // src/harness/pty/tool-server.ts
3770
3924
  import { createServer as createServer2 } from "http";
3771
- import { z as z3 } from "zod";
3925
+ import { z as z4 } from "zod";
3772
3926
  import { writeFile as writeFile3 } from "fs/promises";
3773
3927
  import { join as join2 } from "path";
3774
3928
  import { randomBytes } from "crypto";
@@ -3825,7 +3979,7 @@ var PtyToolServer = class {
3825
3979
  const mcp = new McpServer({ name: this.name, version: "1.0.0" });
3826
3980
  const register = mcp.registerTool.bind(mcp);
3827
3981
  for (const tool2 of this.tools) {
3828
- const inputSchema = tool2.strict ? z3.strictObject(tool2.schema) : tool2.schema;
3982
+ const inputSchema = tool2.strict ? z4.strictObject(tool2.schema) : tool2.schema;
3829
3983
  register(
3830
3984
  tool2.name,
3831
3985
  {
@@ -4095,17 +4249,25 @@ async function readRaw(path4) {
4095
4249
  return null;
4096
4250
  }
4097
4251
  }
4252
+ async function readCredentialsIdentity() {
4253
+ const parsed = parseClaudeAiOauth(await readRaw(claudeCredentialsPath()));
4254
+ if (!parsed) return null;
4255
+ return {
4256
+ accessToken: typeof parsed.accessToken === "string" ? parsed.accessToken : null,
4257
+ hasRefreshToken: typeof parsed.refreshToken === "string" && parsed.refreshToken.length > 0
4258
+ };
4259
+ }
4098
4260
  var READ_BACK_DELAYS_MS = [250, 500, 1e3, 2e3];
4099
4261
  var defaultSleep = (ms) => new Promise((resolve) => {
4100
4262
  setTimeout(resolve, ms);
4101
4263
  });
4102
4264
  async function writeWithReadBackRetry(io2, contents, delaysMs = READ_BACK_DELAYS_MS) {
4103
- const sleep4 = io2.sleep ?? defaultSleep;
4265
+ const sleep2 = io2.sleep ?? defaultSleep;
4104
4266
  for (let attempt = 0; ; attempt++) {
4105
4267
  await io2.write(contents);
4106
4268
  if (await io2.read() === contents) return true;
4107
4269
  if (attempt >= delaysMs.length) return false;
4108
- await sleep4(delaysMs[attempt]);
4270
+ await sleep2(delaysMs[attempt]);
4109
4271
  }
4110
4272
  }
4111
4273
  function fsWriteIo(path4, mode) {
@@ -4445,11 +4607,6 @@ function renderPromptContentText(content) {
4445
4607
  return JSON.stringify(block);
4446
4608
  }).join("\n\n");
4447
4609
  }
4448
- function sleep3(ms) {
4449
- return new Promise((resolve) => {
4450
- setTimeout(resolve, ms);
4451
- });
4452
- }
4453
4610
  async function transcriptSize(path4) {
4454
4611
  try {
4455
4612
  return (await stat2(path4)).size;
@@ -4563,6 +4720,7 @@ var PtySession = class {
4563
4720
  pty = null;
4564
4721
  tempDir = "";
4565
4722
  sawResult = false;
4723
+ limitBannerReported = false;
4566
4724
  // Rolling tail of raw PTY output, retained only to enrich the error when the
4567
4725
  // CLI exits before emitting a result (the bytes are otherwise relayed to S5
4568
4726
  // and never become events). Trimmed to MAX_DIAGNOSTIC_OUTPUT on every write.
@@ -4947,7 +5105,7 @@ var PtySession = class {
4947
5105
  if (text === "" && !this.adapter.capabilities.prefill) return;
4948
5106
  this.writeStdin(this.adapter.encodePromptBytes(text));
4949
5107
  if (this.turn.promptDelivery === "prefill") return;
4950
- await sleep3(resolveSubmitSettleMs());
5108
+ await sleep(resolveSubmitSettleMs());
4951
5109
  if (this._toreDown) return;
4952
5110
  this.writeStdin("\r");
4953
5111
  if (this.adapter.capabilities.structuredEvents) this.armSubmitNudge();
@@ -5093,6 +5251,7 @@ var PtySession = class {
5093
5251
  this.disarmPlanDialogAutoAccept();
5094
5252
  }
5095
5253
  if (this.pendingSubmitNudge) this.disarmSubmitNudge();
5254
+ this.synthesizeRateLimitFromBanner(event);
5096
5255
  this.pushEvent(event);
5097
5256
  if (event.type === "result") {
5098
5257
  this.sawResult = true;
@@ -5100,6 +5259,35 @@ var PtySession = class {
5100
5259
  this.endTurn(true);
5101
5260
  }
5102
5261
  }
5262
+ /**
5263
+ * The interactive CLI reports a hard usage cap only as a conversation banner
5264
+ * ("You've hit your weekly limit · resets 7am (UTC)") — it never writes a
5265
+ * structured rate_limit_event to the transcript. Recognize the banner in
5266
+ * assistant/result text and push the same harness-level event the SDK
5267
+ * harness emits, so cap handling (key cycle → pause) is one code path.
5268
+ * Once per session: the CLI repeats the banner on every rejected turn.
5269
+ */
5270
+ synthesizeRateLimitFromBanner(event) {
5271
+ if (this.limitBannerReported) return;
5272
+ let text;
5273
+ if (event.type === "assistant") {
5274
+ text = event.message.content.map((block) => block.text ?? "").filter(Boolean).join("\n");
5275
+ } else if (event.type === "result" && event.subtype === "success") {
5276
+ text = event.result;
5277
+ }
5278
+ if (!text) return;
5279
+ const match = matchUsageLimitBanner(text);
5280
+ if (!match) return;
5281
+ this.limitBannerReported = true;
5282
+ this.pushEvent({
5283
+ type: "rate_limit_event",
5284
+ rate_limit_info: {
5285
+ status: "rejected",
5286
+ rateLimitType: match.rateLimitType,
5287
+ ...match.resetsAtEpochSeconds === void 0 ? {} : { resetsAt: match.resetsAtEpochSeconds }
5288
+ }
5289
+ });
5290
+ }
5103
5291
  async finalizeOnExit(exitCode) {
5104
5292
  this.coalescer?.flush();
5105
5293
  this.exited = true;
@@ -6104,10 +6292,30 @@ function buildModePrompt(agentMode, context, runnerMode) {
6104
6292
  return buildReviewPrompt(context);
6105
6293
  case "auto":
6106
6294
  return buildAutoPrompt(context, runnerMode);
6295
+ case "chat":
6296
+ return buildChatPrompt();
6107
6297
  default:
6108
6298
  return null;
6109
6299
  }
6110
6300
  }
6301
+ function buildChatPrompt() {
6302
+ return [
6303
+ `
6304
+ ## Mode: Chat`,
6305
+ `You are in Chat mode \u2014 a conversational assistant working directly with the user on this card.`,
6306
+ `- Respond conversationally to the user in chat. Ask clarifying questions when useful; this is a back-and-forth, not an autonomous build.`,
6307
+ `- You have full read/write access to the workspace and can run non-destructive shell commands, so you CAN create files (notes, scripts, docs, data, diagrams, etc.) when they help the user.`,
6308
+ ``,
6309
+ `### Deliverables \u2014 attach, do NOT open a PR`,
6310
+ `- This card has NO pull-request workflow. Do NOT run \`git push\`, do NOT open a PR, and do NOT rely on branch commits to deliver work \u2014 those operations are blocked.`,
6311
+ `- When you create a file the user should keep, attach it to the card with the \`upload_attachment\` tool so it shows up on the card. Mention in chat what you attached.`,
6312
+ ``,
6313
+ `### Finishing the conversation`,
6314
+ `- When the user indicates they are done (or explicitly asks to wrap up / close the card), call \`force_update_task_status\` with status \`"Complete"\` to move the card InProgress \u2192 Done. There is no review or PR step.`,
6315
+ `- If the user is still engaged, keep the card InProgress and keep helping \u2014 only complete it once the interaction has concluded.`,
6316
+ `- Do not complete the card while you still owe the user a response or an attachment.`
6317
+ ].join("\n");
6318
+ }
6111
6319
  function buildReviewPrompt(context) {
6112
6320
  const parts = [
6113
6321
  `
@@ -6707,7 +6915,7 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
6707
6915
  }
6708
6916
 
6709
6917
  // src/tools/task-context-tools.ts
6710
- import { z as z4 } from "zod";
6918
+ import { z as z5 } from "zod";
6711
6919
 
6712
6920
  // src/tools/helpers.ts
6713
6921
  function textResult(text) {
@@ -6741,8 +6949,8 @@ function buildReadTaskChatTool(connection) {
6741
6949
  "read_task_chat",
6742
6950
  "Read recent human/user chat messages for a task. Omit task_id for the current task; pass a child ID for a child's chat. For agent logs use get_execution_logs.",
6743
6951
  {
6744
- limit: z4.number().optional().describe("Number of recent messages to fetch (default 20)"),
6745
- task_id: z4.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
6952
+ limit: z5.number().optional().describe("Number of recent messages to fetch (default 20)"),
6953
+ task_id: z5.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
6746
6954
  },
6747
6955
  async ({ limit, task_id }) => {
6748
6956
  try {
@@ -6786,7 +6994,7 @@ function buildGetTaskTool(connection) {
6786
6994
  "get_task",
6787
6995
  "Look up any task by slug or ID. Returns JSON with id, slug, title, description, plan, status, branch, githubPRNumber, githubPRUrl, storyPoints. For children use list_subtasks.",
6788
6996
  {
6789
- slug_or_id: z4.string().describe("The task slug (e.g. 'my-task') or CUID")
6997
+ slug_or_id: z5.string().describe("The task slug (e.g. 'my-task') or CUID")
6790
6998
  },
6791
6999
  async ({ slug_or_id }) => {
6792
7000
  try {
@@ -6809,9 +7017,9 @@ function buildGetExecutionLogsTool(connection) {
6809
7017
  "get_execution_logs",
6810
7018
  "Read CLI execution logs \u2014 agent reasoning, tool calls, and setup/dev-server output. Filter via source='agent' or 'application'. For human chat use read_task_chat.",
6811
7019
  {
6812
- task_id: z4.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
6813
- source: z4.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
6814
- limit: z4.number().optional().describe("Max number of log entries to return (default 50, max 500).")
7020
+ task_id: z5.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
7021
+ source: z5.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
7022
+ limit: z5.number().optional().describe("Max number of log entries to return (default 50, max 500).")
6815
7023
  },
6816
7024
  async ({ task_id, source, limit }) => {
6817
7025
  try {
@@ -6871,7 +7079,7 @@ function buildGetAttachmentTool(connection) {
6871
7079
  return defineTool(
6872
7080
  "get_attachment",
6873
7081
  "Fetch one task file's content plus metadata by file ID. Call list_task_files first to discover IDs and check sizes \u2014 large binaries may be truncated by the service's size limit.",
6874
- { fileId: z4.string().describe("The file ID to retrieve") },
7082
+ { fileId: z5.string().describe("The file ID to retrieve") },
6875
7083
  async ({ fileId }) => {
6876
7084
  try {
6877
7085
  const file = await connection.call("getTaskFile", {
@@ -6909,7 +7117,7 @@ function buildTaskContextTools(connection) {
6909
7117
  }
6910
7118
 
6911
7119
  // src/tools/dependency-suggestion-tools.ts
6912
- import { z as z5 } from "zod";
7120
+ import { z as z6 } from "zod";
6913
7121
  function buildGetDependenciesTool(connection) {
6914
7122
  return defineTool(
6915
7123
  "get_dependencies",
@@ -6935,10 +7143,10 @@ function buildGetSuggestionsTool(connection) {
6935
7143
  "get_suggestions",
6936
7144
  "List project suggestions sorted by vote score. Filter by status or cap with limit (default 20). Suggestions are project-level ideas, not tasks \u2014 use get_task for tasks.",
6937
7145
  {
6938
- status: z5.string().optional().describe(
7146
+ status: z6.string().optional().describe(
6939
7147
  "Filter by status: Planning, Open, InProgress, ReviewPR, ReviewDev, ReviewLive, Complete, Cancelled"
6940
7148
  ),
6941
- limit: z5.number().int().min(1).max(100).optional().describe("Max results (default 20)")
7149
+ limit: z6.number().int().min(1).max(100).optional().describe("Max results (default 20)")
6942
7150
  },
6943
7151
  async ({ status, limit }) => {
6944
7152
  try {
@@ -6962,14 +7170,14 @@ function buildGetSuggestionsTool(connection) {
6962
7170
  }
6963
7171
 
6964
7172
  // src/tools/mutation-tools.ts
6965
- import { z as z6 } from "zod";
7173
+ import { z as z7 } from "zod";
6966
7174
  function buildPostToChatTool(connection) {
6967
7175
  return defineTool(
6968
7176
  "post_to_chat",
6969
7177
  "Post a message to the task chat for the team to see. Your turn output is NOT shown in chat, so this is the only way the team sees your status, summaries, and questions. Omit task_id to post to the current task's chat; pass a child's ID to message its chat.",
6970
7178
  {
6971
- message: z6.string().describe("The message to post to the team"),
6972
- task_id: z6.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
7179
+ message: z7.string().describe("The message to post to the team"),
7180
+ task_id: z7.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
6973
7181
  },
6974
7182
  async ({ message, task_id }) => {
6975
7183
  try {
@@ -7007,8 +7215,8 @@ function buildForceUpdateTaskStatusTool(connection) {
7007
7215
  "force_update_task_status",
7008
7216
  "EMERGENCY ONLY: force-override a task's Kanban status. Use when an automatic transition failed and the task is wedged. Normal flow transitions status automatically.",
7009
7217
  {
7010
- status: z6.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
7011
- task_id: z6.string().optional().describe("Child task ID to update. Omit to update the current task.")
7218
+ status: z7.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
7219
+ task_id: z7.string().optional().describe("Child task ID to update. Omit to update the current task.")
7012
7220
  },
7013
7221
  async ({ status, task_id }) => {
7014
7222
  try {
@@ -7039,18 +7247,18 @@ function buildCreatePullRequestTool(connection, config) {
7039
7247
  "create_pull_request",
7040
7248
  "Create a GitHub PR for this task. Auto-stages, commits (commitMessage or title default), pushes to origin, then opens the PR. Always use this instead of gh CLI or raw git.",
7041
7249
  {
7042
- title: z6.string().describe("The PR title"),
7043
- body: z6.string().describe("The PR description/body in markdown"),
7044
- branch: z6.string().optional().describe(
7250
+ title: z7.string().describe("The PR title"),
7251
+ body: z7.string().describe("The PR description/body in markdown"),
7252
+ branch: z7.string().optional().describe(
7045
7253
  "The head branch name for the PR. If the task doesn't have a branch set, this will be used. Defaults to the task's existing branch."
7046
7254
  ),
7047
- baseBranch: z6.string().optional().describe(
7255
+ baseBranch: z7.string().optional().describe(
7048
7256
  "The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch."
7049
7257
  ),
7050
- commitMessage: z6.string().optional().describe(
7258
+ commitMessage: z7.string().optional().describe(
7051
7259
  "Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used."
7052
7260
  ),
7053
- skipVerify: z6.boolean().optional().describe(
7261
+ skipVerify: z7.boolean().optional().describe(
7054
7262
  "Controls the local pre-push quality gate (lint/typecheck/test). Defaults to true (--no-verify): the push skips the local gate because you should run gates yourself before opening the PR and CI re-runs them on the resulting PR. Running the full gate synchronously during the push would block the agent's event loop long enough to drop the Conveyor socket connection. Pass false to force the local pre-push hook to run."
7055
7263
  )
7056
7264
  },
@@ -7132,7 +7340,7 @@ function buildAddDependencyTool(connection) {
7132
7340
  "add_dependency",
7133
7341
  "Add a blocking dependency \u2014 this task cannot start until the named task is merged to dev. For post-task follow-ups use create_follow_up_task instead.",
7134
7342
  {
7135
- depends_on_slug_or_id: z6.string().describe("Slug or ID of the task this task depends on")
7343
+ depends_on_slug_or_id: z7.string().describe("Slug or ID of the task this task depends on")
7136
7344
  },
7137
7345
  async ({ depends_on_slug_or_id }) => {
7138
7346
  try {
@@ -7154,7 +7362,7 @@ function buildRemoveDependencyTool(connection) {
7154
7362
  "remove_dependency",
7155
7363
  "Remove a previously added dependency from this task. When to use: the dependency was added in error or is no longer relevant. Returns: confirmation string.",
7156
7364
  {
7157
- depends_on_slug_or_id: z6.string().describe("Slug or ID of the task to remove as dependency")
7365
+ depends_on_slug_or_id: z7.string().describe("Slug or ID of the task to remove as dependency")
7158
7366
  },
7159
7367
  async ({ depends_on_slug_or_id }) => {
7160
7368
  try {
@@ -7176,10 +7384,10 @@ function buildCreateFollowUpTaskTool(connection) {
7176
7384
  "create_follow_up_task",
7177
7385
  "Create a follow-up task that depends on the current task. Use for out-of-scope work or cleanup that should land after this task merges. For blockers use add_dependency.",
7178
7386
  {
7179
- title: z6.string().describe("Follow-up task title"),
7180
- description: z6.string().optional().describe("Brief description of the follow-up work"),
7181
- plan: z6.string().optional().describe("Implementation plan if known"),
7182
- story_point_value: z6.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
7387
+ title: z7.string().describe("Follow-up task title"),
7388
+ description: z7.string().optional().describe("Brief description of the follow-up work"),
7389
+ plan: z7.string().optional().describe("Implementation plan if known"),
7390
+ story_point_value: z7.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
7183
7391
  },
7184
7392
  async ({ title, description, plan, story_point_value }) => {
7185
7393
  try {
@@ -7206,11 +7414,11 @@ function buildCreateSuggestionTool(connection) {
7206
7414
  "create_suggestion",
7207
7415
  "Suggest a feature, improvement, rule, or idea for the project. Duplicates are deduped and your upvote is recorded. For actionable work on this task open a follow-up task.",
7208
7416
  {
7209
- title: z6.string().describe("Short title for the suggestion"),
7210
- description: z6.string().optional().describe(
7417
+ title: z7.string().describe("Short title for the suggestion"),
7418
+ description: z7.string().optional().describe(
7211
7419
  "1-2 sentence description of what should change and why. Keep concise and project-focused."
7212
7420
  ),
7213
- tag_names: z6.array(z6.string()).optional().describe("Tag names to categorize the suggestion")
7421
+ tag_names: z7.array(z7.string()).optional().describe("Tag names to categorize the suggestion")
7214
7422
  },
7215
7423
  async ({ title, description, tag_names }) => {
7216
7424
  try {
@@ -7239,8 +7447,8 @@ function buildVoteSuggestionTool(connection) {
7239
7447
  "vote_suggestion",
7240
7448
  "Vote +1 or -1 on a project suggestion. Use to express support or disagreement with a specific suggestion returned by get_suggestions.",
7241
7449
  {
7242
- suggestion_id: z6.string().describe("The suggestion ID to vote on"),
7243
- value: z6.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
7450
+ suggestion_id: z7.string().describe("The suggestion ID to vote on"),
7451
+ value: z7.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
7244
7452
  },
7245
7453
  async ({ suggestion_id, value }) => {
7246
7454
  try {
@@ -7273,7 +7481,7 @@ function buildMutationTools(connection, config) {
7273
7481
  // src/tools/attachment-tools.ts
7274
7482
  import { readFile as readFile3, stat as stat4 } from "fs/promises";
7275
7483
  import { basename, extname, isAbsolute, join as join5 } from "path";
7276
- import { z as z7 } from "zod";
7484
+ import { z as z8 } from "zod";
7277
7485
  var IMAGE_MIME_BY_EXT = {
7278
7486
  ".png": "image/png",
7279
7487
  ".jpg": "image/jpeg",
@@ -7286,8 +7494,8 @@ function buildUploadAttachmentTool(connection, config) {
7286
7494
  "upload_attachment",
7287
7495
  "Upload an image file (e.g. a Playwright screenshot) as a task attachment AND post it to the task chat in one step \u2014 no follow-up post_to_chat call needed. Supports png/jpg/gif/webp.",
7288
7496
  {
7289
- path: z7.string().describe("Path to the image file \u2014 absolute, or relative to the workspace root"),
7290
- title: z7.string().optional().describe("Short caption posted with the image (defaults to the file name)")
7497
+ path: z8.string().describe("Path to the image file \u2014 absolute, or relative to the workspace root"),
7498
+ title: z8.string().optional().describe("Short caption posted with the image (defaults to the file name)")
7291
7499
  },
7292
7500
  async ({ path: path4, title }) => {
7293
7501
  try {
@@ -7343,7 +7551,7 @@ function buildUploadAttachmentTool(connection, config) {
7343
7551
  }
7344
7552
 
7345
7553
  // src/tools/checklist-tools.ts
7346
- import { z as z8 } from "zod";
7554
+ import { z as z9 } from "zod";
7347
7555
  function buildListManualTestsTool(connection) {
7348
7556
  return defineTool(
7349
7557
  "list_manual_tests",
@@ -7395,8 +7603,8 @@ function buildQueryManualTestsTool(connection) {
7395
7603
  "query_manual_tests",
7396
7604
  "Query manual tests across many tasks in this project, grouped by task. Filter by card status (ReviewDev, ReviewLive, Complete, ...) and/or test status (open | approved | rejected). Use to answer 'show all OPEN manual tests in ReviewDev' or 'show all REJECTED manual tests with the failing reason'. With no filters it defaults to the needs-attention view: open+rejected tests on ReviewDev/ReviewLive cards.",
7397
7605
  {
7398
- cardStatuses: z8.array(z8.string()).optional().describe('Filter tasks by card status, e.g. ["ReviewDev", "ReviewLive"]'),
7399
- testStatuses: z8.array(z8.enum(["open", "approved", "rejected"])).optional().describe("Filter tests by status: open | approved | rejected")
7606
+ cardStatuses: z9.array(z9.string()).optional().describe('Filter tasks by card status, e.g. ["ReviewDev", "ReviewLive"]'),
7607
+ testStatuses: z9.array(z9.enum(["open", "approved", "rejected"])).optional().describe("Filter tests by status: open | approved | rejected")
7400
7608
  },
7401
7609
  async ({ cardStatuses, testStatuses }) => {
7402
7610
  try {
@@ -7420,7 +7628,7 @@ function buildSetManualTestsTool(connection) {
7420
7628
  "set_manual_tests",
7421
7629
  "Add manual test steps to the task checklist. Existing items with the same title are automatically skipped (deduplication). Use to record specific manual verification steps that reviewers should follow when testing this PR.",
7422
7630
  {
7423
- items: z8.array(z8.object({ title: z8.string().min(1).describe("A concise, actionable test step") })).min(1).describe("List of manual test steps to add")
7631
+ items: z9.array(z9.object({ title: z9.string().min(1).describe("A concise, actionable test step") })).min(1).describe("List of manual test steps to add")
7424
7632
  },
7425
7633
  async ({ items }) => {
7426
7634
  try {
@@ -7443,8 +7651,8 @@ function buildEditManualTestTool(connection) {
7443
7651
  "edit_manual_test",
7444
7652
  "Rename an existing manual test step. Identify the test by its current title (case-insensitive); pass the new title to replace it. Use to correct or refine a recorded manual verification step.",
7445
7653
  {
7446
- title: z8.string().min(1).describe("The current title of the manual test to edit"),
7447
- newTitle: z8.string().min(1).describe("The new title for the manual test")
7654
+ title: z9.string().min(1).describe("The current title of the manual test to edit"),
7655
+ newTitle: z9.string().min(1).describe("The new title for the manual test")
7448
7656
  },
7449
7657
  async ({ title, newTitle }) => {
7450
7658
  try {
@@ -7466,7 +7674,7 @@ function buildRemoveManualTestTool(connection) {
7466
7674
  "remove_manual_test",
7467
7675
  "Remove an existing manual test step from the task checklist. Identify the test by its title (case-insensitive). Use to delete a stale or incorrect manual verification step.",
7468
7676
  {
7469
- title: z8.string().min(1).describe("The title of the manual test to remove")
7677
+ title: z9.string().min(1).describe("The title of the manual test to remove")
7470
7678
  },
7471
7679
  async ({ title }) => {
7472
7680
  try {
@@ -7487,7 +7695,7 @@ function buildApproveManualTestTool(connection) {
7487
7695
  "approve_manual_test",
7488
7696
  "Sign off on (approve) a manual test step on behalf of your authenticated user. Identify the test by its title (case-insensitive). Use after you have verified the step passes.",
7489
7697
  {
7490
- title: z8.string().min(1).describe("The title of the manual test to approve")
7698
+ title: z9.string().min(1).describe("The title of the manual test to approve")
7491
7699
  },
7492
7700
  async ({ title }) => {
7493
7701
  try {
@@ -7508,8 +7716,8 @@ function buildRejectManualTestTool(connection) {
7508
7716
  "reject_manual_test",
7509
7717
  "Flag an issue with (reject) a manual test step on behalf of your authenticated user, recording the reason. Identify the test by its title (case-insensitive). Use when the step fails verification.",
7510
7718
  {
7511
- title: z8.string().min(1).describe("The title of the manual test to reject"),
7512
- reason: z8.string().min(1).max(2e3).describe("Why the test failed \u2014 what went wrong, shown to the team")
7719
+ title: z9.string().min(1).describe("The title of the manual test to reject"),
7720
+ reason: z9.string().min(1).max(2e3).describe("Why the test failed \u2014 what went wrong, shown to the team")
7513
7721
  },
7514
7722
  async ({ title, reason }) => {
7515
7723
  try {
@@ -7546,7 +7754,7 @@ function buildCommonTools(connection, config) {
7546
7754
  }
7547
7755
 
7548
7756
  // src/tools/pm-tools.ts
7549
- import { z as z9 } from "zod";
7757
+ import { z as z10 } from "zod";
7550
7758
  var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
7551
7759
  var FOLLOW_PARENT_STATUS_DESCRIPTION = "Child mirrors the parent task's status automatically \u2014 for subtasks that ship on the parent's branch/PR with no build or PR of their own. Manual status writes on a follower stick only until the parent's next transition.";
7552
7760
  var DEPENDS_ON_DESCRIPTION = "Sibling subtask ids or slugs this subtask blocks on (it won't start until they merge to dev). Set explicit dependency metadata here instead of describing order in the plan text \u2014 the pack runner schedules children off these edges. Omit / leave empty for independent children so they run in parallel.";
@@ -7555,8 +7763,8 @@ function buildUpdateTaskTool(connection) {
7555
7763
  "update_task_plan",
7556
7764
  "Save the plan and/or description to the current task. In auto/building mode, save the plan BEFORE writing code and keep it current as the approach evolves \u2014 post it, then build; never pause the build waiting for approval. For children use update_subtask; for title/tags/PR use update_task_properties.",
7557
7765
  {
7558
- plan: z9.string().optional().describe("The task plan in markdown"),
7559
- description: z9.string().optional().describe("Updated task description")
7766
+ plan: z10.string().optional().describe("The task plan in markdown"),
7767
+ description: z10.string().optional().describe("Updated task description")
7560
7768
  },
7561
7769
  async ({ plan, description }) => {
7562
7770
  try {
@@ -7577,13 +7785,13 @@ function buildCreateSubtaskTool(connection) {
7577
7785
  "create_subtask",
7578
7786
  "Create a subtask under the current parent task. Use when breaking a complex parent into smaller pieces during planning. For post-task follow-ups use create_follow_up_task.",
7579
7787
  {
7580
- title: z9.string().describe("Subtask title"),
7581
- description: z9.string().optional().describe("Brief description"),
7582
- plan: z9.string().optional().describe("Implementation plan in markdown"),
7583
- ordinal: z9.number().optional().describe("Step/order number (0-based)"),
7584
- storyPointValue: z9.number().optional().describe(SP_DESCRIPTION),
7585
- followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7586
- dependsOn: z9.array(z9.string()).optional().describe(DEPENDS_ON_DESCRIPTION)
7788
+ title: z10.string().describe("Subtask title"),
7789
+ description: z10.string().optional().describe("Brief description"),
7790
+ plan: z10.string().optional().describe("Implementation plan in markdown"),
7791
+ ordinal: z10.number().optional().describe("Step/order number (0-based)"),
7792
+ storyPointValue: z10.number().optional().describe(SP_DESCRIPTION),
7793
+ followParentStatus: z10.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7794
+ dependsOn: z10.array(z10.string()).optional().describe(DEPENDS_ON_DESCRIPTION)
7587
7795
  },
7588
7796
  async ({
7589
7797
  title,
@@ -7619,20 +7827,20 @@ function buildUpdateSubtaskTool(connection) {
7619
7827
  "update_subtask",
7620
7828
  "Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue, dependsOn) \u2014 and the sanctioned path to make a child buildable: promote it to status Open, assign its agent (agentIdOrName), and set story points. Setting story points does NOT auto-promote; set status explicitly. For the current task use update_task_plan.",
7621
7829
  {
7622
- subtaskId: z9.string().describe("The subtask ID to update"),
7623
- title: z9.string().optional(),
7624
- description: z9.string().optional(),
7625
- plan: z9.string().optional(),
7626
- status: z9.enum(["Planning", "Open"]).optional().describe(
7830
+ subtaskId: z10.string().describe("The subtask ID to update"),
7831
+ title: z10.string().optional(),
7832
+ description: z10.string().optional(),
7833
+ plan: z10.string().optional(),
7834
+ status: z10.enum(["Planning", "Open"]).optional().describe(
7627
7835
  'Move the child between "Planning" and "Open". "Open" marks it ready to execute \u2014 required before start_child_cloud_build. Execution statuses transition automatically.'
7628
7836
  ),
7629
- agentIdOrName: z9.string().optional().describe(
7837
+ agentIdOrName: z10.string().optional().describe(
7630
7838
  "Assign a project agent to the child (agent id or exact name from the Project Agents list). Required before start_child_cloud_build."
7631
7839
  ),
7632
- ordinal: z9.number().optional(),
7633
- storyPointValue: z9.number().optional().describe(SP_DESCRIPTION),
7634
- followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7635
- dependsOn: z9.array(z9.string()).optional().describe(
7840
+ ordinal: z10.number().optional(),
7841
+ storyPointValue: z10.number().optional().describe(SP_DESCRIPTION),
7842
+ followParentStatus: z10.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7843
+ dependsOn: z10.array(z10.string()).optional().describe(
7636
7844
  `${DEPENDS_ON_DESCRIPTION} Replaces the full dependency set \u2014 pass [] to clear all, omit to leave unchanged.`
7637
7845
  )
7638
7846
  },
@@ -7671,7 +7879,7 @@ function buildDeleteSubtaskTool(connection) {
7671
7879
  return defineTool(
7672
7880
  "delete_subtask",
7673
7881
  "Delete a subtask by id. When to use: a subtask was created in error or is no longer needed. Returns: confirmation string.",
7674
- { subtaskId: z9.string().describe("The subtask ID to delete") },
7882
+ { subtaskId: z10.string().describe("The subtask ID to delete") },
7675
7883
  async ({ subtaskId }) => {
7676
7884
  try {
7677
7885
  await connection.call("deleteSubtask", {
@@ -7690,7 +7898,7 @@ function buildListSubtasksTool(connection) {
7690
7898
  "list_subtasks",
7691
7899
  "List all subtasks under the current parent task. Default compact view returns per child: status, agent, story points, PR number/state, dependencies, and holdsBuildSlot \u2014 plus packSlots (in-flight environments vs the PACK_CHILD_LIMIT cap, and which children hold the slots). Use to coordinate child work; pass verbose:true only when you need full description/plan text (large). For non-child tasks use get_task.",
7692
7900
  {
7693
- verbose: z9.boolean().optional().describe(
7901
+ verbose: z10.boolean().optional().describe(
7694
7902
  "Return full task rows including description and plan text (large \u2014 can exceed tool result limits on big packs). Default: compact orchestration view."
7695
7903
  )
7696
7904
  },
@@ -7714,7 +7922,7 @@ function buildPackTools(connection) {
7714
7922
  "start_child_cloud_build",
7715
7923
  "Start a cloud build (codespace) for a child task. Preconditions: child status is `Open`, story points set, and an agent assigned \u2014 satisfy all three with update_subtask (status/agentIdOrName/storyPointValue) first; none happen automatically. A PACK_CHILD_LIMIT error is backpressure, not failure: check list_subtasks packSlots for which children hold the in-flight slots, merge/stop one, then retry.",
7716
7924
  {
7717
- childTaskId: z9.string().describe("The child task ID to start a cloud build for")
7925
+ childTaskId: z10.string().describe("The child task ID to start a cloud build for")
7718
7926
  },
7719
7927
  async ({ childTaskId }) => {
7720
7928
  try {
@@ -7734,7 +7942,7 @@ function buildPackTools(connection) {
7734
7942
  "stop_child_build",
7735
7943
  "Send a graceful stop signal to a running child build's agent. Not a force-kill \u2014 the agent may take a moment to wind down. Stopping a child eventually frees its PACK_CHILD_LIMIT build slot (see list_subtasks packSlots).",
7736
7944
  {
7737
- childTaskId: z9.string().describe("The child task ID whose build should be stopped")
7945
+ childTaskId: z10.string().describe("The child task ID whose build should be stopped")
7738
7946
  },
7739
7947
  async ({ childTaskId }) => {
7740
7948
  try {
@@ -7754,7 +7962,7 @@ function buildPackTools(connection) {
7754
7962
  "approve_and_merge_pr",
7755
7963
  "Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\u2192ReviewDev); false = automerge queued, wait for ReviewDev.",
7756
7964
  {
7757
- childTaskId: z9.string().describe("The child task ID whose PR should be approved and merged")
7965
+ childTaskId: z10.string().describe("The child task ID whose PR should be approved and merged")
7758
7966
  },
7759
7967
  async ({ childTaskId }) => {
7760
7968
  try {
@@ -7792,7 +8000,7 @@ function buildPmTools(connection, options) {
7792
8000
  }
7793
8001
 
7794
8002
  // src/tools/discovery-tools.ts
7795
- import { z as z10 } from "zod";
8003
+ import { z as z11 } from "zod";
7796
8004
  var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique). The key is 'storyPointValue' \u2014 not 'storyPoints'.";
7797
8005
  var VALID_PROPERTY_KEYS = "title, storyPointValue, tagNames, githubPRUrl, githubBranch";
7798
8006
  function buildDiscoveryTools(connection) {
@@ -7801,11 +8009,11 @@ function buildDiscoveryTools(connection) {
7801
8009
  "update_task_properties",
7802
8010
  "Set one or more task properties in a single call. Valid keys: title, storyPointValue, tagNames, githubPRUrl, githubBranch. All are optional \u2014 include only the ones you want to update (at least one). Unknown keys are rejected.",
7803
8011
  {
7804
- title: z10.string().optional().describe("The new task title"),
7805
- storyPointValue: z10.number().optional().describe(SP_DESCRIPTION2),
7806
- tagNames: z10.array(z10.string()).optional().describe("Array of tag names to assign"),
7807
- githubPRUrl: z10.string().url().optional().describe("GitHub pull request URL to link to this task"),
7808
- githubBranch: z10.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
8012
+ title: z11.string().optional().describe("The new task title"),
8013
+ storyPointValue: z11.number().optional().describe(SP_DESCRIPTION2),
8014
+ tagNames: z11.array(z11.string()).optional().describe("Array of tag names to assign"),
8015
+ githubPRUrl: z11.string().url().optional().describe("GitHub pull request URL to link to this task"),
8016
+ githubBranch: z11.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
7809
8017
  },
7810
8018
  async ({ title, storyPointValue, tagNames, githubPRUrl, githubBranch }) => {
7811
8019
  try {
@@ -7846,7 +8054,7 @@ function buildDiscoveryTools(connection) {
7846
8054
  }
7847
8055
 
7848
8056
  // src/tools/code-review-tools.ts
7849
- import { z as z11 } from "zod";
8057
+ import { z as z12 } from "zod";
7850
8058
  async function endReviewSession(connection, reason) {
7851
8059
  await connection.call("endReviewSession", {
7852
8060
  sessionId: connection.sessionId,
@@ -7859,7 +8067,7 @@ function buildCodeReviewTools(connection) {
7859
8067
  "approve_code_review",
7860
8068
  "Approve the code review and exit. Use when the diff passes all review criteria. Takes only a summary \u2014 for changes, use request_code_changes with a structured issues[] list.",
7861
8069
  {
7862
- summary: z11.string().describe("Brief summary of what was reviewed and why it looks good")
8070
+ summary: z12.string().describe("Brief summary of what was reviewed and why it looks good")
7863
8071
  },
7864
8072
  async ({ summary }) => {
7865
8073
  const content = `**Code Review: Approved** :white_check_mark:
@@ -7883,15 +8091,15 @@ ${summary}`;
7883
8091
  "request_code_changes",
7884
8092
  "Request changes during code review and exit. Use when substantive issues must be fixed before merge. Each issue: { file, line?, severity: critical|major|minor, description }.",
7885
8093
  {
7886
- issues: z11.array(
7887
- z11.object({
7888
- file: z11.string().describe("File path where the issue was found"),
7889
- line: z11.number().optional().describe("Line number (if applicable)"),
7890
- severity: z11.enum(["critical", "major", "minor"]).describe("Issue severity"),
7891
- description: z11.string().describe("What is wrong and how to fix it")
8094
+ issues: z12.array(
8095
+ z12.object({
8096
+ file: z12.string().describe("File path where the issue was found"),
8097
+ line: z12.number().optional().describe("Line number (if applicable)"),
8098
+ severity: z12.enum(["critical", "major", "minor"]).describe("Issue severity"),
8099
+ description: z12.string().describe("What is wrong and how to fix it")
7892
8100
  })
7893
8101
  ).describe("List of issues found during review"),
7894
- summary: z11.string().describe("Brief overall summary of the review findings")
8102
+ summary: z12.string().describe("Brief overall summary of the review findings")
7895
8103
  },
7896
8104
  async ({ issues, summary }) => {
7897
8105
  const issueLines = issues.map((issue) => {
@@ -7980,16 +8188,20 @@ function buildConveyorTools(connection, config, context, agentMode) {
7980
8188
  const effectiveMode = agentMode ?? context?.agentMode ?? void 0;
7981
8189
  const commonTools = buildCommonTools(connection, config);
7982
8190
  const modeTools = getModeTools(effectiveMode, connection, config, context);
7983
- const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" || effectiveMode === "building" ? buildDiscoveryTools(connection) : [];
8191
+ const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" || effectiveMode === "building" || effectiveMode === "chat" ? buildDiscoveryTools(connection) : [];
7984
8192
  const codeReviewTools = effectiveMode === "review" ? buildCodeReviewTools(connection) : [];
7985
8193
  const emergencyTools = [buildForceUpdateTaskStatusTool(connection)];
7986
- return withAlwaysLoad([
8194
+ const tools = withAlwaysLoad([
7987
8195
  ...commonTools,
7988
8196
  ...modeTools,
7989
8197
  ...discoveryTools,
7990
8198
  ...codeReviewTools,
7991
8199
  ...emergencyTools
7992
8200
  ]);
8201
+ if (effectiveMode === "chat") {
8202
+ return tools.filter((tool2) => tool2.name !== "create_pull_request");
8203
+ }
8204
+ return tools;
7993
8205
  }
7994
8206
  function createConveyorMcpServer(harness, connection, config, context, agentMode) {
7995
8207
  return harness.createMcpServer({
@@ -8411,6 +8623,13 @@ async function processResultCase(event, host, context, startTime, state) {
8411
8623
  if (info.staleSession) state.staleSession = true;
8412
8624
  if (info.authError) state.authError = true;
8413
8625
  }
8626
+ function processRateLimitCase(event, host, state) {
8627
+ const resetsAt = handleRateLimitEvent(event, host);
8628
+ if (resetsAt) state.rateLimitResetsAt = resetsAt;
8629
+ if (event.rate_limit_info.status === "rejected") {
8630
+ state.rateLimitRejectedType = event.rate_limit_info.rateLimitType ?? "unknown";
8631
+ }
8632
+ }
8414
8633
  async function processEvents(events, context, host) {
8415
8634
  const startTime = Date.now();
8416
8635
  let lastStatusEmit = Date.now();
@@ -8422,6 +8641,7 @@ async function processEvents(events, context, host) {
8422
8641
  sawApiError: false,
8423
8642
  resultSummary: void 0,
8424
8643
  rateLimitResetsAt: void 0,
8644
+ rateLimitRejectedType: void 0,
8425
8645
  staleSession: void 0,
8426
8646
  authError: void 0,
8427
8647
  lastAssistantUsage: void 0,
@@ -8451,11 +8671,9 @@ async function processEvents(events, context, host) {
8451
8671
  case "result":
8452
8672
  await processResultCase(event, host, context, startTime, state);
8453
8673
  break;
8454
- case "rate_limit_event": {
8455
- const resetsAt = handleRateLimitEvent(event, host);
8456
- if (resetsAt) state.rateLimitResetsAt = resetsAt;
8674
+ case "rate_limit_event":
8675
+ processRateLimitCase(event, host, state);
8457
8676
  break;
8458
- }
8459
8677
  case "tool_progress":
8460
8678
  handleToolProgressEvent(event, host);
8461
8679
  break;
@@ -8467,11 +8685,38 @@ async function processEvents(events, context, host) {
8467
8685
  retriable: state.retriable || state.sawApiError,
8468
8686
  resultSummary: state.resultSummary,
8469
8687
  rateLimitResetsAt: state.rateLimitResetsAt,
8688
+ ...state.rateLimitRejectedType && { rateLimitRejectedType: state.rateLimitRejectedType },
8470
8689
  ...state.staleSession && { staleSession: state.staleSession },
8471
8690
  ...state.authError && { authError: state.authError }
8472
8691
  };
8473
8692
  }
8474
8693
 
8694
+ // src/execution/key-cycle.ts
8695
+ var FIVE_HOURS_MS = 5 * 60 * 60 * 1e3;
8696
+ var TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1e3;
8697
+ function applyCycledKeyEnv(envVars, env = process.env) {
8698
+ for (const [key, value] of Object.entries(envVars)) {
8699
+ env[key] = value;
8700
+ }
8701
+ if (envVars.CLAUDE_CODE_OAUTH_TOKEN) {
8702
+ delete env.ANTHROPIC_API_KEY;
8703
+ if (!envVars.CONVEYOR_AGENT_KEY) delete env.CONVEYOR_AGENT_KEY;
8704
+ } else if (envVars.CONVEYOR_AGENT_KEY || envVars.CONVEYOR_OPENCODE_OAUTH) {
8705
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
8706
+ }
8707
+ }
8708
+ async function syncCredentialsAfterCycle(env = process.env) {
8709
+ if (env.CLAUDE_CODE_OAUTH_TOKEN) {
8710
+ await ensureClaudeCredentials(env);
8711
+ } else {
8712
+ await removeConveyorCredentials();
8713
+ }
8714
+ }
8715
+ function fallbackResetIso(rateLimitType, now = Date.now()) {
8716
+ const weekly = /weekly|seven_day/i.test(rateLimitType);
8717
+ return new Date(now + (weekly ? TWENTY_FOUR_HOURS_MS : FIVE_HOURS_MS)).toISOString();
8718
+ }
8719
+
8475
8720
  // src/execution/task-property-utils.ts
8476
8721
  function collectMissingProps(taskProps) {
8477
8722
  const missing = [];
@@ -8541,6 +8786,19 @@ function handleBuildingToolAccess(toolName, input) {
8541
8786
  function handleReviewToolAccess(toolName, input) {
8542
8787
  return handleBuildingToolAccess(toolName, input);
8543
8788
  }
8789
+ var CHAT_BLOCKED_BASH = /\bgit\s+push\b|\bgh\s+pr\b|\bhub\s+pull-request\b/;
8790
+ function handleChatToolAccess(toolName, input) {
8791
+ if (toolName === "Bash") {
8792
+ const cmd = String(input.command ?? "");
8793
+ if (CHAT_BLOCKED_BASH.test(cmd)) {
8794
+ return {
8795
+ behavior: "deny",
8796
+ message: "Chat mode does not open pull requests. Create files locally and attach them to the card with upload_attachment instead of pushing a branch or opening a PR."
8797
+ };
8798
+ }
8799
+ }
8800
+ return handleBuildingToolAccess(toolName, input);
8801
+ }
8544
8802
  function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask) {
8545
8803
  if (hasExitedPlanMode) {
8546
8804
  return isParentTask ? handleReviewToolAccess(toolName, input) : handleBuildingToolAccess(toolName, input);
@@ -8675,6 +8933,8 @@ function resolveToolAccess(host, toolName, input) {
8675
8933
  return handleReviewToolAccess(toolName, input);
8676
8934
  case "auto":
8677
8935
  return handleAutoToolAccess(toolName, input, host.hasExitedPlanMode, host.isParentTask);
8936
+ case "chat":
8937
+ return handleChatToolAccess(toolName, input);
8678
8938
  default:
8679
8939
  return { behavior: "allow", updatedInput: input };
8680
8940
  }
@@ -8694,6 +8954,12 @@ function buildCanUseTool(host) {
8694
8954
  if (toolName === "AskUserQuestion") {
8695
8955
  return await handleAskUserQuestion(host, input);
8696
8956
  }
8957
+ if (host.agentMode === "chat" && /(^|__)create_pull_request$/.test(toolName)) {
8958
+ return {
8959
+ behavior: "deny",
8960
+ message: 'Chat mode does not open pull requests. When the conversation is complete, mark the card done with force_update_task_status("Complete").'
8961
+ };
8962
+ }
8697
8963
  const result = resolveToolAccess(host, toolName, input);
8698
8964
  if (result.behavior === "deny") {
8699
8965
  consecutiveDenials++;
@@ -9294,6 +9560,48 @@ function handleRateLimitPause(host, rateLimitResetsAt) {
9294
9560
  `Rate limited. The task will be automatically re-queued and resume after ${new Date(rateLimitResetsAt).toLocaleString()}.`
9295
9561
  );
9296
9562
  }
9563
+ var MAX_KEY_CYCLES = 5;
9564
+ async function handleUsageCapRejection(context, host, options, rateLimitType, resetsAt) {
9565
+ const pauseAt = resetsAt ?? fallbackResetIso(rateLimitType);
9566
+ if (host.keyCycleCount >= MAX_KEY_CYCLES) {
9567
+ handleRateLimitPause(host, pauseAt);
9568
+ return;
9569
+ }
9570
+ host.keyCycleCount += 1;
9571
+ let response;
9572
+ try {
9573
+ response = await host.connection.cycleCodingAgentKey(rateLimitType, resetsAt);
9574
+ } catch (error) {
9575
+ host.connection.postChatMessage(
9576
+ `Usage cap hit and key cycling failed (${getErrorMessage(error)}) \u2014 pausing until ${new Date(pauseAt).toLocaleString()}.`
9577
+ );
9578
+ handleRateLimitPause(host, pauseAt);
9579
+ return;
9580
+ }
9581
+ if (!response.cycled) {
9582
+ handleRateLimitPause(host, response.resetsAt);
9583
+ return;
9584
+ }
9585
+ applyCycledKeyEnv(response.envVars);
9586
+ await syncCredentialsAfterCycle();
9587
+ await host.harness.dispose?.();
9588
+ host.connection.postChatMessage(
9589
+ `Usage cap hit \u2014 switched to key **${response.label}** and resuming.`
9590
+ );
9591
+ context.claudeSessionId = null;
9592
+ host.connection.storeSessionId("");
9593
+ const freshPrompt = buildMultimodalPrompt(
9594
+ await buildInitialPrompt(host.config.mode, context, host.isAuto, host.agentMode),
9595
+ context,
9596
+ host.harnessKind === "pty"
9597
+ );
9598
+ const freshQuery = host.harness.executeQuery({
9599
+ prompt: host.createInputStream(freshPrompt),
9600
+ options: { ...options, sessionId: void 0 },
9601
+ resume: void 0
9602
+ });
9603
+ return runWithRetry(freshQuery, context, host, options);
9604
+ }
9297
9605
  function handleRetryError(error, context, host, options, prevImageError) {
9298
9606
  if (isStaleOrExitedSession(error, context) && context.claudeSessionId) {
9299
9607
  return handleStaleSession(context, host, options);
@@ -9306,9 +9614,17 @@ function handleRetryError(error, context, host, options, prevImageError) {
9306
9614
  }
9307
9615
  function handleProcessResult(result, context, host, options) {
9308
9616
  if (result.modeRestart || host.isStopped()) return { action: "return" };
9309
- if (result.rateLimitResetsAt) {
9310
- handleRateLimitPause(host, result.rateLimitResetsAt);
9311
- return { action: "return" };
9617
+ if (result.rateLimitRejectedType || result.rateLimitResetsAt) {
9618
+ return {
9619
+ action: "return_promise",
9620
+ promise: handleUsageCapRejection(
9621
+ context,
9622
+ host,
9623
+ options,
9624
+ result.rateLimitRejectedType ?? "unknown",
9625
+ result.rateLimitResetsAt
9626
+ )
9627
+ };
9312
9628
  }
9313
9629
  if (result.staleSession && context.claudeSessionId) {
9314
9630
  return { action: "return_promise", promise: handleStaleSession(context, host, options) };
@@ -9391,6 +9707,7 @@ var QueryBridge = class {
9391
9707
  _discoveryCompleted = false;
9392
9708
  _isParentTask = false;
9393
9709
  _wasRateLimited = false;
9710
+ _keyCycleCount = 0;
9394
9711
  _abortController = null;
9395
9712
  /** Called by SessionRunner when ExitPlanMode triggers a mode transition. */
9396
9713
  onModeTransition;
@@ -9568,6 +9885,12 @@ var QueryBridge = class {
9568
9885
  set wasRateLimited(val) {
9569
9886
  bridge._wasRateLimited = val;
9570
9887
  },
9888
+ get keyCycleCount() {
9889
+ return bridge._keyCycleCount;
9890
+ },
9891
+ set keyCycleCount(val) {
9892
+ bridge._keyCycleCount = val;
9893
+ },
9571
9894
  get activeQuery() {
9572
9895
  return bridge.activeQuery;
9573
9896
  },
@@ -9651,11 +9974,21 @@ function normalizeUsageText(stdout) {
9651
9974
  }
9652
9975
  function parseUsageGauges(stdout) {
9653
9976
  const text = normalizeUsageText(stdout);
9654
- const session = text.match(/Current session[^%\n]*?(\d+(?:\.\d+)?)\s*%(?:\s*used)?/i);
9655
- const weekly = [...text.matchAll(/Current week[^%\n]*?(\d+(?:\.\d+)?)\s*%(?:\s*used)?/gi)];
9977
+ const rows = [
9978
+ ...text.matchAll(
9979
+ /Current (session|week)\s*(\([^)\n]*\))?[^%\n]*?(\d+(?:\.\d+)?)\s*%(?:\s*used)?/gi
9980
+ )
9981
+ ];
9982
+ const gauges = rows.map((m) => ({
9983
+ label: `Current ${m[1].toLowerCase()}${m[2] ? ` ${m[2]}` : ""}`,
9984
+ utilization: Number(m[3]) / 100
9985
+ }));
9986
+ const session = gauges.find((g) => g.label.startsWith("Current session"));
9987
+ const weekly = gauges.filter((g) => g.label.startsWith("Current week"));
9656
9988
  return {
9657
- sessionUsage: session ? Number(session[1]) / 100 : null,
9658
- weeklyUsage: weekly.length ? Math.max(...weekly.map((m) => Number(m[1]))) / 100 : null
9989
+ sessionUsage: session ? session.utilization : null,
9990
+ weeklyUsage: weekly.length ? Math.max(...weekly.map((g) => g.utilization)) : null,
9991
+ gauges
9659
9992
  };
9660
9993
  }
9661
9994
 
@@ -9768,17 +10101,44 @@ async function runUsageProbe(deps = {}) {
9768
10101
 
9769
10102
  // src/execution/usage-sampler.ts
9770
10103
  var logger4 = createServiceLogger("usage-sampler");
9771
- async function sampleKeyUsage(token, probe = () => runUsageProbe(), hasSubscriptionCredentials = () => existsSync3(claudeCredentialsPath())) {
10104
+ function isAttributable(identity, sessionToken) {
10105
+ if (!identity) return { ok: true };
10106
+ if (identity.hasRefreshToken) {
10107
+ return { ok: false, reason: "manual-login-credentials" };
10108
+ }
10109
+ if (sessionToken && identity.accessToken && identity.accessToken !== sessionToken) {
10110
+ return { ok: false, reason: "credentials-token-mismatch" };
10111
+ }
10112
+ return { ok: true };
10113
+ }
10114
+ async function sampleKeyUsage(token, probe = () => runUsageProbe(), hasSubscriptionCredentials = () => existsSync3(claudeCredentialsPath()), readIdentity = readCredentialsIdentity) {
9772
10115
  if (!token && !hasSubscriptionCredentials()) return [];
9773
10116
  try {
10117
+ const attributable = isAttributable(await readIdentity(), token);
10118
+ if (!attributable.ok) {
10119
+ logger4.info("usage sample skipped \u2014 credentials not attributable to this session's key", {
10120
+ reason: attributable.reason
10121
+ });
10122
+ return [];
10123
+ }
9774
10124
  const stdout = await probe();
9775
- const { sessionUsage, weeklyUsage } = parseUsageGauges(stdout);
10125
+ const { sessionUsage, weeklyUsage, gauges } = parseUsageGauges(stdout);
9776
10126
  const samples = [];
9777
10127
  if (sessionUsage !== null) {
9778
- samples.push({ rateLimitType: "five_hour", utilization: sessionUsage, status: "allowed" });
10128
+ samples.push({
10129
+ rateLimitType: "five_hour",
10130
+ utilization: sessionUsage,
10131
+ status: "allowed",
10132
+ gauges
10133
+ });
9779
10134
  }
9780
10135
  if (weeklyUsage !== null) {
9781
- samples.push({ rateLimitType: "seven_day", utilization: weeklyUsage, status: "allowed" });
10136
+ samples.push({
10137
+ rateLimitType: "seven_day",
10138
+ utilization: weeklyUsage,
10139
+ status: "allowed",
10140
+ gauges
10141
+ });
9782
10142
  }
9783
10143
  if (samples.length === 0) {
9784
10144
  logger4.info("usage sample produced no gauges", {
@@ -9959,7 +10319,7 @@ async function readListeningPorts() {
9959
10319
  }
9960
10320
  var DEFAULT_EXCLUDED_PORTS = [2222, 5432, 6379, 9200];
9961
10321
  var DEFAULT_EPHEMERAL_PORT_MIN = 32768;
9962
- var DEFAULT_INTERVAL_MS = 15e3;
10322
+ var DEFAULT_DISCOVERY_INTERVAL_MS = 15e3;
9963
10323
  var DEFAULT_MAX_PORTS = 16;
9964
10324
  var CONFIRM_SCANS = 2;
9965
10325
  var PortDiscovery = class {
@@ -9985,7 +10345,7 @@ var PortDiscovery = class {
9985
10345
  lastReportedKey = "";
9986
10346
  constructor(options) {
9987
10347
  this.opts = options;
9988
- this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;
10348
+ this.intervalMs = options.intervalMs ?? DEFAULT_DISCOVERY_INTERVAL_MS;
9989
10349
  this.maxPorts = options.maxPorts ?? DEFAULT_MAX_PORTS;
9990
10350
  this.excluded = new Set(options.excludedPorts ?? DEFAULT_EXCLUDED_PORTS);
9991
10351
  this.ephemeralPortMin = options.ephemeralPortMin ?? DEFAULT_EPHEMERAL_PORT_MIN;
@@ -10173,7 +10533,7 @@ function isHeavyGateActive() {
10173
10533
  }
10174
10534
 
10175
10535
  // src/runner/session-runner.ts
10176
- var AUTO_RUN_MODES = /* @__PURE__ */ new Set(["building", "auto", "review", "discovery"]);
10536
+ var AUTO_RUN_MODES = /* @__PURE__ */ new Set(["building", "auto", "review", "discovery", "chat"]);
10177
10537
  var SessionRunner = class _SessionRunner {
10178
10538
  connection;
10179
10539
  mode;
@@ -10744,7 +11104,8 @@ var SessionRunner = class _SessionRunner {
10744
11104
  type: "rate_limit_update",
10745
11105
  rateLimitType: sample.rateLimitType,
10746
11106
  utilization: sample.utilization,
10747
- status: sample.status
11107
+ status: sample.status,
11108
+ gauges: sample.gauges
10748
11109
  });
10749
11110
  }
10750
11111
  }
@@ -11251,6 +11612,7 @@ export {
11251
11612
  ClaudeTuiAdapter,
11252
11613
  PtyHarness,
11253
11614
  createServiceLogger,
11615
+ GIT_TIMEOUT_MS,
11254
11616
  hasUncommittedChanges,
11255
11617
  getCurrentBranch,
11256
11618
  hasUnpushedCommits,
@@ -11281,4 +11643,4 @@ export {
11281
11643
  runStartCommand,
11282
11644
  unshallowRepo
11283
11645
  };
11284
- //# sourceMappingURL=chunk-LBMFXTIV.js.map
11646
+ //# sourceMappingURL=chunk-BN5TDTW7.js.map