dsh-llm-verifier 0.6.7 → 0.6.9

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.
@@ -361,7 +361,7 @@ function blockText$1(blocks) {
361
361
  * @param blocks - content blocks of an `assistant/message` event.
362
362
  * @returns The joined text, trimmed.
363
363
  */
364
- function narrativeText(blocks) {
364
+ function narrativeText$1(blocks) {
365
365
  const parts = [];
366
366
  const visit = (items) => {
367
367
  for (const block of items) if (block.type === "text") parts.push(block.text);
@@ -433,7 +433,7 @@ function buildEvidenceIndex(events) {
433
433
  }
434
434
  } else if (event.type === "assistant/message") {
435
435
  const blocks = event.data?.message?.content ?? event.data?.content;
436
- const text = narrativeText(Array.isArray(blocks) ? blocks : []);
436
+ const text = narrativeText$1(Array.isArray(blocks) ? blocks : []);
437
437
  if (text) narration = {
438
438
  seq: event.seq,
439
439
  text
@@ -648,7 +648,7 @@ const VERIFIER_EVIDENCE_TOOLS = /* @__PURE__ */ new Set([
648
648
  "verifier_current_session"
649
649
  ]);
650
650
  /** Tools that return either a child's report (evidence) or a bare start acknowledgement (not evidence). */
651
- const SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["subagent", "subagent_fork"]);
651
+ const SUBAGENT_TOOLS$1 = /* @__PURE__ */ new Set(["subagent", "subagent_fork"]);
652
652
  /**
653
653
  * Start acknowledgement of a background child.
654
654
  *
@@ -672,7 +672,7 @@ function isEvidenceOutput(name, text) {
672
672
  if (BOOKKEEPING_TOOLS.has(name) || VERIFIER_EVIDENCE_TOOLS.has(name)) return false;
673
673
  const body = text.trim();
674
674
  if (!body) return false;
675
- return !(SUBAGENT_TOOLS.has(name) && CHILD_START_ACKNOWLEDGEMENT.test(body));
675
+ return !(SUBAGENT_TOOLS$1.has(name) && CHILD_START_ACKNOWLEDGEMENT.test(body));
676
676
  }
677
677
  /** Signatures of an output that reports a PASSED verification result. */
678
678
  const VERIFICATION_PASS_SIGNATURES = [
@@ -1776,7 +1776,8 @@ const PASSIVE_TOOLS = /* @__PURE__ */ new Set([
1776
1776
  "list_agents",
1777
1777
  "get_goal",
1778
1778
  "skill",
1779
- "mcp__codegraph__codegraph_explore"
1779
+ "mcp__codegraph__codegraph_explore",
1780
+ "ask_user_question"
1780
1781
  ]);
1781
1782
  const VERIFIER_TOOLS = /* @__PURE__ */ new Set([
1782
1783
  "verifier_compare",
@@ -1883,6 +1884,236 @@ function isSuccessfulCodeDispatch(data) {
1883
1884
  if (Array.isArray(data.content) && data.content.some((b) => b.isError === true)) return false;
1884
1885
  return true;
1885
1886
  }
1887
+ const SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["subagent", "subagent_fork"]);
1888
+ const CONTINUABLE_SUBAGENT_START = /^\s*started subagent\s+([^\s`]+)/imu;
1889
+ const BACKGROUND_SUBAGENT_JOB_START = /^\s*started background subagent job\s+([^\s`]+)/imu;
1890
+ const GENERAL_SUBAGENT_START = /^\s*started (?:background )?subagent\b/imu;
1891
+ /**
1892
+ * Whether background subagents started during the current task remain in flight.
1893
+ *
1894
+ * A background subagent returns immediately with a start receipt (`started subagent <id>`
1895
+ * or `started background subagent job <id>`) and settles later via a runtime-injected notice
1896
+ * (`source.kind === 'subagent-settled'` or a job settlement notice). Performing session
1897
+ * acceptance while subagents are in flight will always fail and steer prematurely because the
1898
+ * delegated work has not reported back yet.
1899
+ * @param events - session events.
1900
+ * @param taskStartSeq - sequence number of the current direct user task statement.
1901
+ * @returns True when at least one background subagent remains unsettled.
1902
+ */
1903
+ function hasPendingSubagents(events, taskStartSeq) {
1904
+ const relevant = events.filter((event) => event.seq >= taskStartSeq);
1905
+ const pendingContinuable = /* @__PURE__ */ new Map();
1906
+ const pendingJobs = /* @__PURE__ */ new Map();
1907
+ let anonymousPendingCount = 0;
1908
+ const calls = /* @__PURE__ */ new Map();
1909
+ for (const event of relevant) if (event.type === "tool/call") calls.set(String(event.data.callId), event);
1910
+ for (const event of relevant) {
1911
+ if (event.type === "tool/result") {
1912
+ const call = calls.get(String(event.data.message.source.callId));
1913
+ if (call && SUBAGENT_TOOLS.has(call.data.name) && event.data.error === void 0) {
1914
+ if (event.data.message.content.every((b) => b.isError !== true)) {
1915
+ const text = blockText(event.data.message.content);
1916
+ const contMatch = text.match(CONTINUABLE_SUBAGENT_START);
1917
+ const jobMatch = text.match(BACKGROUND_SUBAGENT_JOB_START);
1918
+ if (contMatch) pendingContinuable.set(contMatch[1], event.seq);
1919
+ else if (jobMatch) pendingJobs.set(jobMatch[1], event.seq);
1920
+ else if (GENERAL_SUBAGENT_START.test(text)) anonymousPendingCount += 1;
1921
+ }
1922
+ }
1923
+ } else if (CODE_DISPATCH_TYPES.has(event.type)) {
1924
+ const data = event.data;
1925
+ if (data && SUBAGENT_TOOLS.has(data.name) && isSuccessfulCodeDispatch(data)) {
1926
+ const text = blockText(data.content);
1927
+ const contMatch = text.match(CONTINUABLE_SUBAGENT_START);
1928
+ const jobMatch = text.match(BACKGROUND_SUBAGENT_JOB_START);
1929
+ if (contMatch) pendingContinuable.set(contMatch[1], event.seq);
1930
+ else if (jobMatch) pendingJobs.set(jobMatch[1], event.seq);
1931
+ else if (GENERAL_SUBAGENT_START.test(text)) anonymousPendingCount += 1;
1932
+ }
1933
+ }
1934
+ if (event.type === "user/message") {
1935
+ const source = event.data?.source;
1936
+ const text = blockText(event.data?.content);
1937
+ if (source?.kind === "subagent-settled") {
1938
+ const senderId = typeof source.senderSessionId === "string" ? source.senderSessionId : void 0;
1939
+ if (senderId && pendingContinuable.has(senderId)) pendingContinuable.delete(senderId);
1940
+ else {
1941
+ let found = false;
1942
+ for (const [id] of pendingContinuable) if (text.includes(id)) {
1943
+ pendingContinuable.delete(id);
1944
+ found = true;
1945
+ break;
1946
+ }
1947
+ if (!found) {
1948
+ if (pendingContinuable.size > 0) {
1949
+ const oldest = pendingContinuable.keys().next().value;
1950
+ if (oldest !== void 0) pendingContinuable.delete(oldest);
1951
+ } else if (anonymousPendingCount > 0) anonymousPendingCount -= 1;
1952
+ }
1953
+ }
1954
+ } else if (source?.plugin === "tool-jobs" || /background job\b.*finished/iu.test(text)) {
1955
+ for (const [jobId] of pendingJobs) if (text.includes(jobId)) {
1956
+ pendingJobs.delete(jobId);
1957
+ break;
1958
+ }
1959
+ }
1960
+ }
1961
+ if (event.type === "tool/call") {
1962
+ const name = event.data.name;
1963
+ const argsText = event.data.arguments;
1964
+ let parsedArgs = {};
1965
+ if (typeof argsText === "string") try {
1966
+ parsedArgs = JSON.parse(argsText);
1967
+ } catch {}
1968
+ else if (typeof argsText === "object" && argsText !== null) parsedArgs = argsText;
1969
+ if (name === "interrupt_agent") {
1970
+ const target = String(parsedArgs.target ?? parsedArgs.agent_id ?? "");
1971
+ if (target && pendingContinuable.has(target)) pendingContinuable.delete(target);
1972
+ } else if (name === "job_kill") {
1973
+ const jobId = String(parsedArgs.job_id ?? "");
1974
+ if (jobId && pendingJobs.has(jobId)) pendingJobs.delete(jobId);
1975
+ }
1976
+ } else if (CODE_DISPATCH_TYPES.has(event.type)) {
1977
+ const data = event.data;
1978
+ if (data) {
1979
+ const name = data.name;
1980
+ let parsedArgs = {};
1981
+ if (typeof data.arguments === "string") try {
1982
+ parsedArgs = JSON.parse(data.arguments);
1983
+ } catch {}
1984
+ else if (typeof data.arguments === "object" && data.arguments !== null) parsedArgs = data.arguments;
1985
+ if (name === "interrupt_agent") {
1986
+ const target = String(parsedArgs.target ?? parsedArgs.agent_id ?? "");
1987
+ if (target && pendingContinuable.has(target)) pendingContinuable.delete(target);
1988
+ } else if (name === "job_kill") {
1989
+ const jobId = String(parsedArgs.job_id ?? "");
1990
+ if (jobId && pendingJobs.has(jobId)) pendingJobs.delete(jobId);
1991
+ }
1992
+ }
1993
+ }
1994
+ }
1995
+ return pendingContinuable.size > 0 || pendingJobs.size > 0 || anonymousPendingCount > 0;
1996
+ }
1997
+ function parseArgumentsObject(value) {
1998
+ if (typeof value === "string") try {
1999
+ const parsed = JSON.parse(value);
2000
+ return typeof parsed === "object" && parsed !== null ? parsed : {};
2001
+ } catch {
2002
+ return {};
2003
+ }
2004
+ return typeof value === "object" && value !== null ? value : {};
2005
+ }
2006
+ const USER_QUESTION_PATTERNS = [
2007
+ /[??]\s*["'))』」]*\s*$/u,
2008
+ /(?:请|麻烦您?)(?:告知|确认|指示|选择|提供|决定|回复)/u,
2009
+ /(?:等待|静待|等)(?:您的|你的|您|你|用户)?(?:确认|指示|回复|决定|指令|反馈|选择|输入)/u,
2010
+ /(?:如果您?|如|若)(?:希望|需要|想)(?:继续|执行).*(?:请|告诉我|告知)/u,
2011
+ /(?:是否|要不要|可否)(?:需要我?|继续|同意|允许|采用).*[??]?/u,
2012
+ /(?:暂时|先|已)?暂停(?:工作|执行|后续).*(?:等|指示|确认|决定|用户)/u,
2013
+ /\b(?:please\s+(?:confirm|let\s+me\s+know|advise|choose|select|provide|indicate|tell\s+me|reply))\b/iu,
2014
+ /\b(?:waiting\s+for|awaiting)\s+(?:your\s+|user\s+)?(?:input|instructions?|reply|response|confirmation|decision|guidance|feedback)\b/iu,
2015
+ /\b(?:would\s+you\s+like|should\s+i|do\s+you\s+want\s+me\s+to|how\s+would\s+you\s+like|which\s+(?:option|approach|strategy)\s+do\s+you\s+prefer)\b/iu,
2016
+ /\b(?:let\s+me\s+know\s+(?:how|what|if|whether|when))\b/iu,
2017
+ /\b(?:paused?\s+(?:work|execution|here|for\s+now)|stopping\s+here)\b/iu
2018
+ ];
2019
+ function isAwaitingUserText(text) {
2020
+ const trimmed = text.trim();
2021
+ if (!trimmed) return false;
2022
+ const lastLine = trimmed.split("\n").filter((l) => l.trim()).at(-1) ?? "";
2023
+ return USER_QUESTION_PATTERNS.some((p) => p.test(lastLine) || p.test(trimmed));
2024
+ }
2025
+ function narrativeText(blocks) {
2026
+ if (typeof blocks === "string") return blocks.trim();
2027
+ if (!Array.isArray(blocks)) return "";
2028
+ const parts = [];
2029
+ for (const block of blocks) if (block?.type === "text" && typeof block.text === "string") parts.push(block.text);
2030
+ else if (block?.type === "tool-result") parts.push(blockText(block.content));
2031
+ return parts.join("\n").trim();
2032
+ }
2033
+ /**
2034
+ * Whether the agent has paused to ask the user a question, obtain confirmation, or await user instructions.
2035
+ *
2036
+ * During task execution, an agent may legitimately pause to ask the operator a question
2037
+ * (e.g. calling `ask_user_question`, pausing/blocking a goal, or concluding a turn with prose
2038
+ * awaiting user guidance). Gating or steering in this state forces the model to keep executing,
2039
+ * overriding the user interaction boundary and locking the user out of providing guidance.
2040
+ *
2041
+ * Returns undefined when the work has already reached its delivery phase (all todos completed
2042
+ * with verification evidence), because in that state the agent is delivering the task rather than
2043
+ * pausing for input.
2044
+ */
2045
+ function inspectUserInteractionPause(events, taskStartSeq, currentTurn) {
2046
+ const delivery = inspectDeliveryPhase(events);
2047
+ if (delivery?.todosComplete && delivery.verification !== void 0) return;
2048
+ let turnEvents = events;
2049
+ if (currentTurn !== void 0) {
2050
+ const turnStartIndex = events.findLastIndex((e) => e.type === "turn/start" && e.data.turn === currentTurn);
2051
+ if (turnStartIndex >= 0) turnEvents = events.slice(turnStartIndex);
2052
+ else {
2053
+ const byTurn = events.filter((e) => e.data?.turn === currentTurn);
2054
+ if (byTurn.length > 0) turnEvents = byTurn;
2055
+ }
2056
+ } else {
2057
+ const lastTurnStart = events.findLastIndex((e) => e.type === "turn/start");
2058
+ if (lastTurnStart >= 0) turnEvents = events.slice(lastTurnStart);
2059
+ }
2060
+ let lastAskUserSeq = -1;
2061
+ for (const event of turnEvents) if (event.type === "tool/call") {
2062
+ if (event.data.name === "ask_user_question") lastAskUserSeq = Math.max(lastAskUserSeq, event.seq);
2063
+ } else if (CODE_DISPATCH_TYPES.has(event.type)) {
2064
+ if (event.data?.name === "ask_user_question") lastAskUserSeq = Math.max(lastAskUserSeq, event.seq);
2065
+ }
2066
+ if (lastAskUserSeq >= 0) {
2067
+ if (!turnEvents.some((event) => {
2068
+ if (event.seq <= lastAskUserSeq) return false;
2069
+ if (event.type === "tool/call") return isConsequential(event.data.name);
2070
+ if (CODE_DISPATCH_TYPES.has(event.type)) {
2071
+ const data = event.data;
2072
+ return data ? isConsequential(data.name) : false;
2073
+ }
2074
+ return false;
2075
+ })) return {
2076
+ paused: true,
2077
+ reason: "ask_user_question in current turn"
2078
+ };
2079
+ }
2080
+ const taskEvents = events.filter((e) => e.seq >= taskStartSeq);
2081
+ let goalPhase;
2082
+ for (const event of taskEvents) if (event.type === "tool/call") {
2083
+ const call = event;
2084
+ if (call.data.name === "update_goal") {
2085
+ const args = parseArgumentsObject(call.data.arguments);
2086
+ if (args.action === "pause") goalPhase = "paused";
2087
+ else if (args.action === "blocked") goalPhase = "blocked";
2088
+ else if (args.action === "resume") goalPhase = "active";
2089
+ else if (args.action === "complete") goalPhase = "complete";
2090
+ }
2091
+ } else if (CODE_DISPATCH_TYPES.has(event.type)) {
2092
+ const data = event.data;
2093
+ if (data?.name === "update_goal") {
2094
+ const args = parseArgumentsObject(data.arguments);
2095
+ if (args.action === "pause") goalPhase = "paused";
2096
+ else if (args.action === "blocked") goalPhase = "blocked";
2097
+ else if (args.action === "resume") goalPhase = "active";
2098
+ else if (args.action === "complete") goalPhase = "complete";
2099
+ }
2100
+ }
2101
+ if (goalPhase === "paused" || goalPhase === "blocked") return {
2102
+ paused: true,
2103
+ reason: "goal is " + goalPhase
2104
+ };
2105
+ const lastAssistant = turnEvents.filter((e) => e.type === "assistant/message").at(-1);
2106
+ if (lastAssistant && lastAssistant.type === "assistant/message") {
2107
+ const content = lastAssistant.data.message?.content ?? [];
2108
+ if (!content.some((b) => b.type === "tool-call")) {
2109
+ const text = narrativeText(content);
2110
+ if (text && isAwaitingUserText(text)) return {
2111
+ paused: true,
2112
+ reason: "assistant awaiting user instructions"
2113
+ };
2114
+ }
2115
+ }
2116
+ }
1886
2117
  function analyzeAutoTask(events, policy, sessionId) {
1887
2118
  const taskStartSeq = latestDirectUserSeq(events);
1888
2119
  if (taskStartSeq === void 0) return {
@@ -1892,6 +2123,8 @@ function analyzeAutoTask(events, policy, sessionId) {
1892
2123
  consequentialToolCalls: 0,
1893
2124
  hasManualSessionVerification: false,
1894
2125
  manualVerificationAccepted: false,
2126
+ pendingSubagents: false,
2127
+ pendingUserInteraction: false,
1895
2128
  eligible: false,
1896
2129
  reason: "no-direct-user-task"
1897
2130
  };
@@ -1949,6 +2182,8 @@ function analyzeAutoTask(events, policy, sessionId) {
1949
2182
  criteria: verdict.criteria
1950
2183
  }, policy.threshold) && !stale(verdict.toSeq);
1951
2184
  });
2185
+ const pendingSubagents = hasPendingSubagents(events, taskStartSeq);
2186
+ const pendingUserInteraction = inspectUserInteractionPause(events, taskStartSeq) !== void 0;
1952
2187
  if (policy.mode === "manual") return {
1953
2188
  taskStartSeq,
1954
2189
  toolCalls,
@@ -1956,6 +2191,8 @@ function analyzeAutoTask(events, policy, sessionId) {
1956
2191
  consequentialToolCalls,
1957
2192
  hasManualSessionVerification,
1958
2193
  manualVerificationAccepted,
2194
+ pendingSubagents,
2195
+ pendingUserInteraction,
1959
2196
  eligible: false,
1960
2197
  reason: "manual-mode"
1961
2198
  };
@@ -1966,9 +2203,35 @@ function analyzeAutoTask(events, policy, sessionId) {
1966
2203
  consequentialToolCalls,
1967
2204
  hasManualSessionVerification,
1968
2205
  manualVerificationAccepted,
2206
+ pendingSubagents,
2207
+ pendingUserInteraction,
1969
2208
  eligible: false,
1970
2209
  reason: "already-verified"
1971
2210
  };
2211
+ if (pendingSubagents) return {
2212
+ taskStartSeq,
2213
+ toolCalls,
2214
+ completedToolResults,
2215
+ consequentialToolCalls,
2216
+ hasManualSessionVerification,
2217
+ manualVerificationAccepted,
2218
+ pendingSubagents: true,
2219
+ pendingUserInteraction,
2220
+ eligible: false,
2221
+ reason: "pending-subagents"
2222
+ };
2223
+ if (pendingUserInteraction) return {
2224
+ taskStartSeq,
2225
+ toolCalls,
2226
+ completedToolResults,
2227
+ consequentialToolCalls,
2228
+ hasManualSessionVerification,
2229
+ manualVerificationAccepted,
2230
+ pendingSubagents,
2231
+ pendingUserInteraction: true,
2232
+ eligible: false,
2233
+ reason: "user-interaction-paused"
2234
+ };
1972
2235
  if (consequentialToolCalls === 0) return {
1973
2236
  taskStartSeq,
1974
2237
  toolCalls,
@@ -1976,6 +2239,8 @@ function analyzeAutoTask(events, policy, sessionId) {
1976
2239
  consequentialToolCalls,
1977
2240
  hasManualSessionVerification,
1978
2241
  manualVerificationAccepted,
2242
+ pendingSubagents,
2243
+ pendingUserInteraction,
1979
2244
  eligible: false,
1980
2245
  reason: "no-consequential-work"
1981
2246
  };
@@ -1986,6 +2251,8 @@ function analyzeAutoTask(events, policy, sessionId) {
1986
2251
  consequentialToolCalls,
1987
2252
  hasManualSessionVerification,
1988
2253
  manualVerificationAccepted,
2254
+ pendingSubagents,
2255
+ pendingUserInteraction,
1989
2256
  eligible: false,
1990
2257
  reason: "no-completed-evidence"
1991
2258
  };
@@ -1996,6 +2263,8 @@ function analyzeAutoTask(events, policy, sessionId) {
1996
2263
  consequentialToolCalls,
1997
2264
  hasManualSessionVerification,
1998
2265
  manualVerificationAccepted,
2266
+ pendingSubagents,
2267
+ pendingUserInteraction,
1999
2268
  eligible: false,
2000
2269
  reason: "insufficient-tool-evidence"
2001
2270
  };
@@ -2006,6 +2275,8 @@ function analyzeAutoTask(events, policy, sessionId) {
2006
2275
  consequentialToolCalls,
2007
2276
  hasManualSessionVerification,
2008
2277
  manualVerificationAccepted,
2278
+ pendingSubagents,
2279
+ pendingUserInteraction,
2009
2280
  eligible: true,
2010
2281
  reason: policy.mode + "-eligible"
2011
2282
  };
@@ -2173,6 +2444,6 @@ function selectRouteFeedbackDetail(candidates, result, maxChars = MAX_ROUTE_FEED
2173
2444
  ].join("\n"));
2174
2445
  }
2175
2446
  //#endregion
2176
- export { verificationFailed as A, latestDirectUserSeq as C, semanticDecision as D, routedRepeats as E, ScoreCache as F, SingleFlight as I, resolveCacheFile as L, extractSession as M, sanitizeVerifierText as N, semanticReferencesVisible as O, sessionEvents as P, stableHash as R, itemBudget as S, parseSemanticRoute as T, buildSemanticRoutePrompt as _, compareRouteFeedbackDetail as a, inspectDeliveryPhase as b, selectRouteFeedbackDetail as c, AutoVerifierRouter as d, MAX_ROUTED_CHECKPOINTS as f, buildEvidenceIndex as g, boundDecision as h, automaticFeedback as i, verificationVerdict as j, semanticRouteHint as k, sessionAccepted as l, analyzeStructuredRoute as m, PROPOSAL_FEEDBACK_NOTE as n, failedAcceptanceCriteria as o, RECOVERY_FAILURE_CONTEXT_CHARS as p, analyzeAutoTask as r, isSubagentSession as s, MAX_ROUTE_FEEDBACK_CHARS as t, topScoreIndices as u, buildSemanticRouteView as v, nextDiagnosticCycleId as w, inspectRecoverySignal as x, estimateRoutedCalls as y };
2447
+ export { semanticDecision as A, resolveCacheFile as B, inspectDeliveryPhase as C, nextDiagnosticCycleId as D, latestDirectUserSeq as E, extractSession as F, sanitizeVerifierText as I, sessionEvents as L, semanticRouteHint as M, verificationFailed as N, parseSemanticRoute as O, verificationVerdict as P, ScoreCache as R, estimateRoutedCalls as S, itemBudget as T, stableHash as V, analyzeStructuredRoute as _, compareRouteFeedbackDetail as a, buildSemanticRoutePrompt as b, inspectUserInteractionPause as c, selectRouteFeedbackDetail as d, sessionAccepted as f, RECOVERY_FAILURE_CONTEXT_CHARS as g, MAX_ROUTED_CHECKPOINTS as h, automaticFeedback as i, semanticReferencesVisible as j, routedRepeats as k, isAwaitingUserText as l, AutoVerifierRouter as m, PROPOSAL_FEEDBACK_NOTE as n, failedAcceptanceCriteria as o, topScoreIndices as p, analyzeAutoTask as r, hasPendingSubagents as s, MAX_ROUTE_FEEDBACK_CHARS as t, isSubagentSession as u, boundDecision as v, inspectRecoverySignal as w, buildSemanticRouteView as x, buildEvidenceIndex as y, SingleFlight as z };
2177
2448
 
2178
- //# sourceMappingURL=auto-DkUMv8FV.js.map
2449
+ //# sourceMappingURL=auto-C9YG0E22.js.map