ur-agent 1.65.10 → 1.65.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -56962,13 +56962,19 @@ function normalizeQuestionOption(value) {
56962
56962
  const option = objectValue(value);
56963
56963
  if (!option)
56964
56964
  return null;
56965
- const label = typeof option.label === "string" && option.label.trim() ? option.label.trim() : typeof option.value === "string" && option.value.trim() ? option.value.trim() : "";
56966
- const description = typeof option.description === "string" && option.description.trim() ? option.description.trim() : label;
56967
- if (!label || !description)
56965
+ if (!sameKeys(option, ["label"], ["description", "preview"]))
56968
56966
  return null;
56967
+ if (typeof option.label !== "string" || !option.label.trim())
56968
+ return null;
56969
+ if (option.description !== undefined && (typeof option.description !== "string" || !option.description.trim())) {
56970
+ return null;
56971
+ }
56972
+ if (option.preview !== undefined && typeof option.preview !== "string") {
56973
+ return null;
56974
+ }
56969
56975
  return {
56970
- label,
56971
- description,
56976
+ label: option.label.trim(),
56977
+ ...typeof option.description === "string" ? { description: option.description.trim() } : {},
56972
56978
  ...typeof option.preview === "string" ? { preview: option.preview } : {}
56973
56979
  };
56974
56980
  }
@@ -56988,10 +56994,14 @@ function normalizeQuestion(value, index2) {
56988
56994
  ]);
56989
56995
  if (!questionText || !Array.isArray(question.options))
56990
56996
  return null;
56991
- const options = question.options.map(normalizeQuestionOption).filter((option) => option !== null);
56992
- if (options.length < 2 || options.length > 4)
56997
+ const normalizedOptions = question.options.map(normalizeQuestionOption);
56998
+ if (!normalizedOptions.every((option) => option !== null)) {
56993
56999
  return null;
56994
- const header = typeof question.header === "string" && question.header.trim() ? question.header.trim().slice(0, 12) : headerFromQuestion(questionText, index2);
57000
+ }
57001
+ const options = normalizedOptions;
57002
+ if (options.length < 2 || options.length > 8)
57003
+ return null;
57004
+ const header = typeof question.header === "string" && question.header.trim() ? question.header.trim() : headerFromQuestion(questionText, index2);
56995
57005
  return {
56996
57006
  question: questionText,
56997
57007
  header,
@@ -57295,135 +57305,7 @@ function synthesizeKimiToolCalls(message) {
57295
57305
  m.content = [...kept, ...synthesized];
57296
57306
  m.stop_reason = "tool_use";
57297
57307
  }
57298
- function clarifyHeader(question) {
57299
- const word = question.replace(/[^A-Za-z0-9]+/g, " ").split(/\s+/).find((part) => part && !CLARIFY_HEADER_STOP_WORDS.has(part.toLowerCase()));
57300
- return (word ?? "Options").slice(0, 12);
57301
- }
57302
- function cleanOption(raw) {
57303
- let opt = raw.trim();
57304
- opt = opt.replace(/^[\s"'`*_\-\u2013\u2014]+/, "").replace(/[\s"'`*_.?!,;:]+$/g, "");
57305
- for (let i2 = 0;i2 < 3; i2++) {
57306
- const before = opt;
57307
- opt = opt.replace(OPTION_LEADIN_RE, "").replace(OPTION_QUESTION_LEADIN_RE, "");
57308
- if (opt === before)
57309
- break;
57310
- }
57311
- opt = opt.replace(OPTION_TRAILING_QUALIFIER_RE, "");
57312
- opt = opt.replace(/\b(?:instead|please|etc\.?)$/i, "");
57313
- return opt.replace(/[\s,;:]+$/g, "").trim();
57314
- }
57315
- function splitEnumeration(s) {
57316
- if (!/\bor\b/i.test(s))
57317
- return null;
57318
- const parts = s.split(/\s*,?\s+or\s+|\s*,\s*/gi).map((p) => p.trim()).filter(Boolean);
57319
- return parts.length >= 2 ? parts : null;
57320
- }
57321
- function extractClarifyOptions(text) {
57322
- const trimmed = text.trim();
57323
- if (!trimmed)
57324
- return [];
57325
- const clauses = trimmed.split(/(?<=[?.!;])\s+/).map((c3) => c3.trim()).filter(Boolean);
57326
- const options = [];
57327
- for (const clause of clauses) {
57328
- const stripped = clause.replace(OPTION_LEADIN_RE, "");
57329
- const candidates = splitEnumeration(stripped) ?? [stripped];
57330
- for (const candidate of candidates) {
57331
- const cleaned = cleanOption(candidate);
57332
- if (!cleaned || cleaned.length > 120)
57333
- continue;
57334
- if (OPTION_CATCHALL_RE.test(cleaned))
57335
- continue;
57336
- options.push(cleaned);
57337
- }
57338
- }
57339
- const seen = new Set;
57340
- const unique = [];
57341
- for (const opt of options) {
57342
- const key = opt.toLowerCase();
57343
- if (seen.has(key))
57344
- continue;
57345
- seen.add(key);
57346
- unique.push(opt);
57347
- if (unique.length === 4)
57348
- break;
57349
- }
57350
- return unique;
57351
- }
57352
- function buildClarifyQuestion(segment) {
57353
- const s = segment.replace(/^\s*(?:\d+[.)]|[-*\u2022])\s+/, "").replace(/\*\*/g, "").trim();
57354
- const qEnd = s.indexOf("?");
57355
- if (qEnd === -1)
57356
- return null;
57357
- const question = s.slice(0, qEnd + 1).trim();
57358
- const remainder = s.slice(qEnd + 1).trim();
57359
- let options = extractClarifyOptions(remainder);
57360
- if (options.length < 2) {
57361
- const inner = question.replace(/\?+$/, "");
57362
- const lastClause = (inner.split(/(?<=[.!;])\s+/).pop() ?? inner).trim();
57363
- if (/\bor\b/i.test(lastClause)) {
57364
- const inline = extractClarifyOptions(lastClause + ".");
57365
- if (inline.length >= 2)
57366
- options = inline;
57367
- }
57368
- }
57369
- if (options.length < 2)
57370
- return null;
57371
- return {
57372
- question,
57373
- header: clarifyHeader(question),
57374
- options: options.map((label) => ({ label, description: label }))
57375
- };
57376
- }
57377
- function parseClarifyingQuestions(text, options = {}) {
57378
- if (!hasTool(options.availableToolNames, "AskUserQuestion"))
57379
- return null;
57380
- const trimmed = text.trim();
57381
- if (!trimmed || trimmed.length > CLARIFY_MAX_LEN)
57382
- return null;
57383
- if (trimmed.includes("```") || trimmed.includes("<|"))
57384
- return null;
57385
- const lines = trimmed.split(`
57386
- `).map((l) => l.trim()).filter(Boolean);
57387
- if (lines.length === 0 || !lines[lines.length - 1].endsWith("?"))
57388
- return null;
57389
- const isListItem = (l) => /^(?:\d+[.)]|[-*\u2022])\s+/.test(l);
57390
- let segments;
57391
- if (lines.some(isListItem)) {
57392
- segments = [];
57393
- for (const line of lines) {
57394
- if (isListItem(line) || segments.length === 0)
57395
- segments.push(line);
57396
- else
57397
- segments[segments.length - 1] += " " + line;
57398
- }
57399
- } else {
57400
- segments = trimmed.split(/\n{2,}/).map((s) => s.replace(/\n/g, " ").trim()).filter((s) => s.includes("?"));
57401
- if (segments.length === 0)
57402
- segments = [trimmed.replace(/\n/g, " ")];
57403
- }
57404
- const questions = [];
57405
- const seenQuestions = new Set;
57406
- for (const segment of segments) {
57407
- if (questions.length === 4)
57408
- break;
57409
- const built = buildClarifyQuestion(segment);
57410
- if (!built)
57411
- continue;
57412
- const key = built.question.toLowerCase();
57413
- if (seenQuestions.has(key))
57414
- continue;
57415
- seenQuestions.add(key);
57416
- questions.push(built);
57417
- }
57418
- if (questions.length === 0)
57419
- return null;
57420
- return {
57421
- id: `clarify_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,
57422
- name: "AskUserQuestion",
57423
- input: { questions }
57424
- };
57425
- }
57426
- var SECTION_RE, CALL_RE, STRAY_RE, KimiToolCallParseError, CLARIFY_MAX_LEN = 2000, OPTION_LEADIN_RE, OPTION_QUESTION_LEADIN_RE, OPTION_CATCHALL_RE, OPTION_TRAILING_QUALIFIER_RE, CLARIFY_HEADER_STOP_WORDS;
57308
+ var SECTION_RE, CALL_RE, STRAY_RE, KimiToolCallParseError;
57427
57309
  var init_kimiToolCalls = __esm(() => {
57428
57310
  init_json();
57429
57311
  SECTION_RE = /<\|tool_calls_section_begin\|>([\s\S]*?)<\|tool_calls_section_end\|>/g;
@@ -57436,41 +57318,6 @@ var init_kimiToolCalls = __esm(() => {
57436
57318
  Object.setPrototypeOf(this, new.target.prototype);
57437
57319
  }
57438
57320
  };
57439
- OPTION_LEADIN_RE = /^(?:and\s+)?(?:or|also|just|maybe|perhaps|either|alternatively|optionally|well)\b[\s,:]*/i;
57440
- OPTION_QUESTION_LEADIN_RE = /^(?:(?:do|would|should|could|can|will)\s+(?:you|we|i)\s+(?:want|prefer|like|need|use|go\s+with|have)?|you\s+(?:could|can|might|may)|i\s+(?:could|can|would|might)|we\s+(?:could|can|might)|want|prefer|pick|choose|use|go\s+with|how\s+about|what\s+about)\b[\s,:]*/i;
57441
- OPTION_CATCHALL_RE = /^(?:(?:or\s+)?(?:something|anything|someone)\s+else|other(?:\s+option)?|none(?:\s+of\s+(?:the\s+)?(?:above|these))?|no|nope|not\s+sure|any(?:thing)?|else|you\s+(?:choose|decide|pick)|your\s+(?:call|choice))$/i;
57442
- OPTION_TRAILING_QUALIFIER_RE = /\s+(?:is|are|would\s+be|seems?|sounds?|looks?)\s+(?:the\s+)?(?:simplest|easiest|best|recommended|fastest|cleanest|most\s+\w+)(?:\s+(?:option|choice|approach))?$/i;
57443
- CLARIFY_HEADER_STOP_WORDS = new Set([
57444
- "a",
57445
- "about",
57446
- "also",
57447
- "an",
57448
- "and",
57449
- "are",
57450
- "be",
57451
- "can",
57452
- "could",
57453
- "do",
57454
- "does",
57455
- "for",
57456
- "i",
57457
- "is",
57458
- "or",
57459
- "should",
57460
- "support",
57461
- "that",
57462
- "the",
57463
- "this",
57464
- "to",
57465
- "want",
57466
- "we",
57467
- "what",
57468
- "which",
57469
- "with",
57470
- "without",
57471
- "would",
57472
- "you"
57473
- ]);
57474
57321
  });
57475
57322
 
57476
57323
  // src/services/api/ollama.ts
@@ -57481,6 +57328,7 @@ __export(exports_ollama, {
57481
57328
  mergeToolCalls: () => mergeToolCalls,
57482
57329
  isOllamaCloudModel: () => isOllamaCloudModel2,
57483
57330
  getOllamaRequestTimeoutMs: () => getOllamaRequestTimeoutMs,
57331
+ getOllamaModelDefaultTimeoutMs: () => getOllamaModelDefaultTimeoutMs,
57484
57332
  getEffectiveOllamaBaseUrl: () => getEffectiveOllamaBaseUrl,
57485
57333
  createOllamaURHQClient: () => createOllamaURHQClient,
57486
57334
  consumePendingProviderNotice: () => consumePendingProviderNotice,
@@ -57633,14 +57481,21 @@ function getOllamaRequestTimeoutMs(options, env4 = process.env, model) {
57633
57481
  if (isTruthyEnv(env4.UR_CODE_REMOTE)) {
57634
57482
  return REMOTE_OLLAMA_REQUEST_TIMEOUT_MS;
57635
57483
  }
57484
+ return getOllamaModelDefaultTimeoutMs(model);
57485
+ }
57486
+ function isOllamaCloudModel2(model) {
57487
+ return model?.trim().toLowerCase().endsWith(":cloud") ?? false;
57488
+ }
57489
+ function getOllamaModelDefaultTimeoutMs(model) {
57490
+ const normalized = model?.trim().toLowerCase() ?? "";
57491
+ if (/^kimi-k2\.7(?:[-.:]|$)/.test(normalized) && isOllamaCloudModel2(model)) {
57492
+ return KIMI_CLOUD_REQUEST_TIMEOUT_MS;
57493
+ }
57636
57494
  if (isOllamaCloudModel2(model)) {
57637
57495
  return CLOUD_OLLAMA_REQUEST_TIMEOUT_MS;
57638
57496
  }
57639
57497
  return DEFAULT_OLLAMA_REQUEST_TIMEOUT_MS;
57640
57498
  }
57641
- function isOllamaCloudModel2(model) {
57642
- return model?.trim().toLowerCase().endsWith(":cloud") ?? false;
57643
- }
57644
57499
  function isTruthyEnv(value) {
57645
57500
  if (!value) {
57646
57501
  return false;
@@ -58115,11 +57970,6 @@ async function* streamURHQEvents(response, params, controller, requestId, textTo
58115
57970
  if (textToolFallbackAllowed) {
58116
57971
  const kimiParsed = parseKimiToolCalls(text);
58117
57972
  textToolCalls.push(...kimiParsed.toolCalls);
58118
- if (toolCalls.length === 0 && textToolCalls.length === 0) {
58119
- const clarify = parseClarifyingQuestions(text, { availableToolNames });
58120
- if (clarify)
58121
- textToolCalls.push(clarify);
58122
- }
58123
57973
  }
58124
57974
  const normalizedToolUses = normalizeOllamaToolUses(toolCalls, textToolCalls, availableToolNames, "Ollama stream");
58125
57975
  for (const call of normalizedToolUses) {
@@ -58260,9 +58110,6 @@ function ollamaResponseToURHQMessage(response, params, textToolFallbackAllowed)
58260
58110
  }) : { text: rawText, toolCalls: [] };
58261
58111
  const text = parsedText.text;
58262
58112
  const textToolCalls = [...parsedText.toolCalls];
58263
- const clarifyCall = textToolFallbackAllowed && structured.length === 0 && textToolCalls.length === 0 ? parseClarifyingQuestions(text, { availableToolNames }) : null;
58264
- if (clarifyCall)
58265
- textToolCalls.push(clarifyCall);
58266
58113
  const normalizedToolUses = normalizeOllamaToolUses(structured, textToolCalls, availableToolNames, "Ollama response");
58267
58114
  if (thinking) {
58268
58115
  content.push({
@@ -58577,7 +58424,7 @@ function parseToolInput(input) {
58577
58424
  }
58578
58425
  return normalized;
58579
58426
  }
58580
- var DEFAULT_OLLAMA_REQUEST_TIMEOUT_MS = 300000, REMOTE_OLLAMA_REQUEST_TIMEOUT_MS = 120000, CLOUD_OLLAMA_REQUEST_TIMEOUT_MS = 120000, OLLAMA_GATEWAY_TIMEOUT_MESSAGE = "Ollama gateway timed out while waiting for the model to respond. Check the selected Ollama endpoint or increase API_TIMEOUT_MS if the model needs more time.", ollamaModelCapabilitiesCache, warnedToolsUnsupportedModels, TEXT_TOOL_CALL_HINT, pendingProviderNotice = null, LEVELED_THINK_MODEL_RE;
58427
+ var DEFAULT_OLLAMA_REQUEST_TIMEOUT_MS = 300000, REMOTE_OLLAMA_REQUEST_TIMEOUT_MS = 120000, CLOUD_OLLAMA_REQUEST_TIMEOUT_MS = 120000, KIMI_CLOUD_REQUEST_TIMEOUT_MS = 300000, OLLAMA_GATEWAY_TIMEOUT_MESSAGE = "Ollama gateway timed out while waiting for the model to respond. Check the selected Ollama endpoint or increase API_TIMEOUT_MS if the model needs more time.", ollamaModelCapabilitiesCache, warnedToolsUnsupportedModels, TEXT_TOOL_CALL_HINT, pendingProviderNotice = null, LEVELED_THINK_MODEL_RE;
58581
58428
  var init_ollama = __esm(() => {
58582
58429
  init_urhq_sdk();
58583
58430
  init_ollamaModels();
@@ -75597,7 +75444,7 @@ var init_auth = __esm(() => {
75597
75444
 
75598
75445
  // src/utils/userAgent.ts
75599
75446
  function getURCodeUserAgent() {
75600
- return `ur/${"1.65.10"}`;
75447
+ return `ur/${"1.65.12"}`;
75601
75448
  }
75602
75449
 
75603
75450
  // src/utils/workloadContext.ts
@@ -75619,7 +75466,7 @@ function getUserAgent() {
75619
75466
  const clientApp = process.env.UR_AGENT_SDK_CLIENT_APP ? `, client-app/${process.env.UR_AGENT_SDK_CLIENT_APP}` : "";
75620
75467
  const workload = getWorkload();
75621
75468
  const workloadSuffix = workload ? `, workload/${workload}` : "";
75622
- return `ur-cli/${"1.65.10"} (${process.env.USER_TYPE}, ${process.env.UR_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
75469
+ return `ur-cli/${"1.65.12"} (${process.env.USER_TYPE}, ${process.env.UR_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
75623
75470
  }
75624
75471
  function getMCPUserAgent() {
75625
75472
  const parts = [];
@@ -75633,7 +75480,7 @@ function getMCPUserAgent() {
75633
75480
  parts.push(`client-app/${process.env.UR_AGENT_SDK_CLIENT_APP}`);
75634
75481
  }
75635
75482
  const suffix = parts.length > 0 ? ` (${parts.join(", ")})` : "";
75636
- return `ur/${"1.65.10"}${suffix}`;
75483
+ return `ur/${"1.65.12"}${suffix}`;
75637
75484
  }
75638
75485
  function getWebFetchUserAgent() {
75639
75486
  return `UR-User (${getURCodeUserAgent()})`;
@@ -75771,7 +75618,7 @@ var init_user = __esm(() => {
75771
75618
  deviceId,
75772
75619
  sessionId: getSessionId(),
75773
75620
  email: getEmail(),
75774
- appVersion: "1.65.10",
75621
+ appVersion: "1.65.12",
75775
75622
  platform: getHostPlatformForAnalytics(),
75776
75623
  organizationUuid,
75777
75624
  accountUuid,
@@ -83971,7 +83818,7 @@ var init_metadata = __esm(() => {
83971
83818
  COMPOUND_OPERATOR_REGEX = /\s*(?:&&|\|\||[;|])\s*/;
83972
83819
  WHITESPACE_REGEX = /\s+/;
83973
83820
  getVersionBase = memoize_default(() => {
83974
- const match = "1.65.10".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
83821
+ const match = "1.65.12".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
83975
83822
  return match ? match[0] : undefined;
83976
83823
  });
83977
83824
  buildEnvContext = memoize_default(async () => {
@@ -84011,7 +83858,7 @@ var init_metadata = __esm(() => {
84011
83858
  isGithubAction: isEnvTruthy(process.env.GITHUB_ACTIONS),
84012
83859
  isURCodeAction: isEnvTruthy(process.env.UR_CODE_ACTION),
84013
83860
  isURAiAuth: isURAISubscriber(),
84014
- version: "1.65.10",
83861
+ version: "1.65.12",
84015
83862
  versionBase: getVersionBase(),
84016
83863
  buildTime: "",
84017
83864
  deploymentEnvironment: env2.detectDeploymentEnvironment(),
@@ -84681,7 +84528,7 @@ function initialize1PEventLogging() {
84681
84528
  const platform2 = getPlatform();
84682
84529
  const attributes = {
84683
84530
  [import_semantic_conventions4.ATTR_SERVICE_NAME]: "ur",
84684
- [import_semantic_conventions4.ATTR_SERVICE_VERSION]: "1.65.10"
84531
+ [import_semantic_conventions4.ATTR_SERVICE_VERSION]: "1.65.12"
84685
84532
  };
84686
84533
  if (platform2 === "wsl") {
84687
84534
  const wslVersion = getWslVersion();
@@ -84709,7 +84556,7 @@ function initialize1PEventLogging() {
84709
84556
  })
84710
84557
  ]
84711
84558
  });
84712
- firstPartyEventLogger = firstPartyEventLoggerProvider.getLogger("com.urhq.ur.events", "1.65.10");
84559
+ firstPartyEventLogger = firstPartyEventLoggerProvider.getLogger("com.urhq.ur.events", "1.65.12");
84713
84560
  }
84714
84561
  async function reinitialize1PEventLoggingIfConfigChanged() {
84715
84562
  if (!is1PEventLoggingEnabled() || !firstPartyEventLoggerProvider) {
@@ -94597,7 +94444,7 @@ function formatAgentTrendReport(report = buildAgentTrendReport()) {
94597
94444
  function formatA2AAgentCard(options = {}, pretty = true) {
94598
94445
  return JSON.stringify(buildA2AAgentCard(options), null, pretty ? 2 : 0);
94599
94446
  }
94600
- var urVersion = "1.65.10", researchSnapshotDate = "2026-07-15", coverage, priorityRoadmap;
94447
+ var urVersion = "1.65.12", researchSnapshotDate = "2026-07-15", coverage, priorityRoadmap;
94601
94448
  var init_trends = __esm(() => {
94602
94449
  init_a2aCardSignature();
94603
94450
  coverage = [
@@ -97400,7 +97247,7 @@ function getAttributionHeader(fingerprint) {
97400
97247
  if (!isAttributionHeaderEnabled()) {
97401
97248
  return "";
97402
97249
  }
97403
- const version2 = `${"1.65.10"}.${fingerprint}`;
97250
+ const version2 = `${"1.65.12"}.${fingerprint}`;
97404
97251
  const entrypoint = process.env.UR_CODE_ENTRYPOINT ?? "unknown";
97405
97252
  const cch = "";
97406
97253
  const workload = getWorkload();
@@ -97921,6 +97768,10 @@ function getWriteToolDescription() {
97921
97768
 
97922
97769
  Usage:
97923
97770
  - This tool will overwrite the existing file if there is one at the provided path.${getPreReadInstruction()}
97771
+ - Every call must include both required fields in the same structured invocation: \`file_path\` and the complete literal file text in \`content\`.
97772
+ - Put the actual file text inside \`content\`; surrounding assistant prose is never copied into the file. Never call Write with only a path, and never invent or recover missing content from prose.
97773
+ - An empty \`content\` string creates an empty file. Use it only when an empty file is genuinely intended.
97774
+ - A file is not created or updated until this tool returns a success result. If validation fails, correct the arguments and retry; do not claim the write succeeded.
97924
97775
  - Prefer the Edit tool for modifying existing files \u2014 it only sends the diff. Only use this tool to create new files or for complete rewrites.
97925
97776
  - NEVER create documentation files (*.md) or README files unless explicitly requested by the User.
97926
97777
  - Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.`;
@@ -155269,7 +155120,7 @@ var init_projectSafety = __esm(() => {
155269
155120
  function getInstruments() {
155270
155121
  if (instruments)
155271
155122
  return instruments;
155272
- const meter = import_api10.metrics.getMeter("ur-agent.gen_ai", "1.65.10");
155123
+ const meter = import_api10.metrics.getMeter("ur-agent.gen_ai", "1.65.12");
155273
155124
  instruments = {
155274
155125
  operationDuration: meter.createHistogram("gen_ai.client.operation.duration", {
155275
155126
  description: "GenAI operation duration.",
@@ -155367,7 +155218,7 @@ function genAiAgentAttributes() {
155367
155218
  "gen_ai.operation.name": GEN_AI_OPERATION_INVOKE_AGENT,
155368
155219
  "gen_ai.provider.name": "ur",
155369
155220
  "gen_ai.agent.name": "UR-Nexus",
155370
- "gen_ai.agent.version": "1.65.10"
155221
+ "gen_ai.agent.version": "1.65.12"
155371
155222
  };
155372
155223
  }
155373
155224
  function genAiWorkflowAttributes(workflowName) {
@@ -155383,7 +155234,7 @@ function genAiWorkflowAttributes(workflowName) {
155383
155234
  function startGenAiWorkflowSpan(workflowName) {
155384
155235
  const attributes = genAiWorkflowAttributes(workflowName);
155385
155236
  const name = typeof attributes["gen_ai.workflow.name"] === "string" ? `invoke_workflow ${attributes["gen_ai.workflow.name"]}` : GEN_AI_OPERATION_INVOKE_WORKFLOW;
155386
- return import_api10.trace.getTracer("ur-agent.gen_ai", "1.65.10").startSpan(name, { kind: import_api10.SpanKind.INTERNAL, attributes });
155237
+ return import_api10.trace.getTracer("ur-agent.gen_ai", "1.65.12").startSpan(name, { kind: import_api10.SpanKind.INTERNAL, attributes });
155387
155238
  }
155388
155239
  function endGenAiWorkflowSpan(span, options2 = {}) {
155389
155240
  try {
@@ -155421,7 +155272,7 @@ function startGenAiMemorySpan(operation, options2 = {}) {
155421
155272
  if (options2.recordCount !== undefined && Number.isInteger(options2.recordCount) && options2.recordCount >= 0) {
155422
155273
  attributes["gen_ai.memory.record.count"] = options2.recordCount;
155423
155274
  }
155424
- return import_api10.trace.getTracer("ur-agent.gen_ai", "1.65.10").startSpan(operation, { kind: import_api10.SpanKind.INTERNAL, attributes });
155275
+ return import_api10.trace.getTracer("ur-agent.gen_ai", "1.65.12").startSpan(operation, { kind: import_api10.SpanKind.INTERNAL, attributes });
155425
155276
  }
155426
155277
  function endGenAiMemorySpan(span, options2 = {}) {
155427
155278
  try {
@@ -248904,7 +248755,7 @@ function getTelemetryAttributes() {
248904
248755
  attributes["session.id"] = sessionId;
248905
248756
  }
248906
248757
  if (shouldIncludeAttribute("OTEL_METRICS_INCLUDE_VERSION")) {
248907
- attributes["app.version"] = "1.65.10";
248758
+ attributes["app.version"] = "1.65.12";
248908
248759
  }
248909
248760
  const oauthAccount = getOauthAccountInfo();
248910
248761
  if (oauthAccount) {
@@ -265115,11 +264966,11 @@ Preview content is rendered as markdown in a monospace box. Multi-line text with
265115
264966
  html: `
265116
264967
  Preview feature:
265117
264968
  Use the optional \`preview\` field on options when presenting concrete artifacts that users need to visually compare:
265118
- - HTML mockups of UI layouts or components
265119
- - Formatted code snippets showing different implementations
265120
- - Visual comparisons or diagrams
264969
+ - Plain-text or ASCII mockups of UI layouts or components
264970
+ - Inert code snippets showing different implementations
264971
+ - Textual visual comparisons or diagrams
265121
264972
 
265122
- Preview content must be a self-contained HTML fragment (no <html>/<body> wrapper, no <script> or <style> tags \u2014 use inline style attributes instead). Do not use previews for simple preference questions where labels and descriptions suffice. Note: previews are only supported for single-select questions (not multiSelect).
264973
+ Preview content is untrusted text: raw HTML is not accepted or executed. It is escaped and rendered as inert preformatted text. Do not include HTML tags, attributes, URLs, scripts, styles, event handlers, or other executable markup. Do not use previews for simple preference questions where labels and descriptions suffice. Note: previews are only supported for single-select questions (not multiSelect).
265123
264974
  `
265124
264975
  };
265125
264976
  ASK_USER_QUESTION_TOOL_PROMPT = `Use this tool when you need to ask the user questions during execution. This allows you to:
@@ -265130,10 +264981,20 @@ Preview content must be a self-contained HTML fragment (no <html>/<body> wrapper
265130
264981
 
265131
264982
  Strongly prefer this tool over asking a question in plain assistant text. Any time your reply would end with a question that offers the user options or asks them to choose a direction (e.g. "Would you like A or B?", "Which approach should I take?", "Want me to do X or Y?"), call this tool with those options instead so the user gets a selectable arrow-key menu. Only ask in plain text when the answer is genuinely open-ended and cannot be expressed as a small set of choices.
265132
264983
 
264984
+ Strict input hierarchy:
264985
+ - Invoke the tool with exactly one top-level \`questions\` array containing 1-4 complete question objects.
264986
+ - Every question object contains \`question\`, a concise \`header\` (maximum 12 characters), and an \`options\` array with 2-8 option objects. Use \`multiSelect: true\` only when more than one choice may apply.
264987
+ - Every option object contains a \`label\`. Add \`description\` only when it contributes a real consequence, trade-off, or limitation; \`preview\` is optional.
264988
+ - Keep each question and its own options nested together. Never put option rows directly in the top-level \`questions\` array, and never send incomplete header/prompt-only entries.
264989
+
264990
+ Canonical valid tool arguments (invoke the structured tool; do not print this object as prose):
264991
+ {"questions":[{"question":"Which database should we use?","header":"Database","options":[{"label":"PostgreSQL (Recommended)","description":"Strong consistency and concurrency; requires a running server and migrations."},{"label":"SQLite","description":"Zero setup and a single file; unsuitable for multiple concurrent writers."}],"multiSelect":false}]}
264992
+
265133
264993
  Usage notes:
265134
264994
  - Users will always be able to select "Other" to provide custom text input, so it is safe to offer choices even when you are unsure you have listed every option
265135
264995
  - Use multiSelect: true to allow multiple answers to be selected for a question
265136
264996
  - If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
264997
+ - Do not over-question. Ask only decisions that materially affect the result and cannot be inferred safely. If more than four decisions are truly needed, ask the most blocking 1-4 first and ask the remainder in a later round.
265137
264998
 
265138
264999
  Writing the three fields \u2014 they must each carry DIFFERENT information:
265139
265000
  - \`header\` names the dimension being decided ("Database", "Auth method"). It is not a shortened copy of the question.
@@ -295438,7 +295299,7 @@ function getInstallationEnv() {
295438
295299
  return;
295439
295300
  }
295440
295301
  function getURCodeVersion() {
295441
- return "1.65.10";
295302
+ return "1.65.12";
295442
295303
  }
295443
295304
  async function getInstalledVSCodeExtensionVersion(command) {
295444
295305
  const { stdout } = await execFileNoThrow(command, ["--list-extensions", "--show-versions"], {
@@ -302769,7 +302630,7 @@ async function setupSdkMcpClients(sdkMcpConfigs, sendMcpMessage) {
302769
302630
  const client2 = new Client({
302770
302631
  name: "ur",
302771
302632
  title: "UR",
302772
- version: "1.65.10",
302633
+ version: "1.65.12",
302773
302634
  description: "UR-Nexus autonomous engineering workflow engine",
302774
302635
  websiteUrl: PRODUCT_URL
302775
302636
  }, {
@@ -303129,7 +302990,7 @@ var init_client5 = __esm(() => {
303129
302990
  const client2 = new Client({
303130
302991
  name: "ur",
303131
302992
  title: "UR",
303132
- version: "1.65.10",
302993
+ version: "1.65.12",
303133
302994
  description: "UR-Nexus autonomous engineering workflow engine",
303134
302995
  websiteUrl: PRODUCT_URL
303135
302996
  }, {
@@ -315668,7 +315529,7 @@ async function createRuntime() {
315668
315529
  bootstrapTelemetry();
315669
315530
  const resource = defaultResource().merge(detectResources({ detectors: [envDetector] })).merge(resourceFromAttributes({
315670
315531
  [import_semantic_conventions7.ATTR_SERVICE_NAME]: "ur-agent",
315671
- [import_semantic_conventions7.ATTR_SERVICE_VERSION]: "1.65.10"
315532
+ [import_semantic_conventions7.ATTR_SERVICE_VERSION]: "1.65.12"
315672
315533
  }));
315673
315534
  const tracerProvider = exporters.traces.length > 0 ? new BasicTracerProvider({
315674
315535
  resource,
@@ -315701,11 +315562,11 @@ async function createRuntime() {
315701
315562
  setMeterProvider(meterProvider);
315702
315563
  setLoggerProvider(loggerProvider);
315703
315564
  if (meterProvider) {
315704
- const meter = meterProvider.getMeter("ur-agent", "1.65.10");
315565
+ const meter = meterProvider.getMeter("ur-agent", "1.65.12");
315705
315566
  setMeter(meter, (name, options2) => meter.createCounter(name, options2));
315706
315567
  }
315707
315568
  if (loggerProvider) {
315708
- setEventLogger(loggerProvider.getLogger("ur-agent.events", "1.65.10"));
315569
+ setEventLogger(loggerProvider.getLogger("ur-agent.events", "1.65.12"));
315709
315570
  }
315710
315571
  if (!cleanupRegistered2) {
315711
315572
  cleanupRegistered2 = true;
@@ -316367,9 +316228,9 @@ async function assertMinVersion() {
316367
316228
  if (false) {}
316368
316229
  try {
316369
316230
  const versionConfig = await getDynamicConfig_BLOCKS_ON_INIT("tengu_version_config", { minVersion: "0.0.0" });
316370
- if (versionConfig.minVersion && lt("1.65.10", versionConfig.minVersion)) {
316231
+ if (versionConfig.minVersion && lt("1.65.12", versionConfig.minVersion)) {
316371
316232
  console.error(`
316372
- It looks like your version of UR (${"1.65.10"}) needs an update.
316233
+ It looks like your version of UR (${"1.65.12"}) needs an update.
316373
316234
  A newer version (${versionConfig.minVersion} or higher) is required to continue.
316374
316235
 
316375
316236
  To update, please run:
@@ -316585,7 +316446,7 @@ async function installGlobalPackage(specificVersion) {
316585
316446
  logError2(new AutoUpdaterError("Another process is currently installing an update"));
316586
316447
  logEvent("tengu_auto_updater_lock_contention", {
316587
316448
  pid: process.pid,
316588
- currentVersion: "1.65.10"
316449
+ currentVersion: "1.65.12"
316589
316450
  });
316590
316451
  return "in_progress";
316591
316452
  }
@@ -316594,7 +316455,7 @@ async function installGlobalPackage(specificVersion) {
316594
316455
  if (!env2.isRunningWithBun() && env2.isNpmFromWindowsPath()) {
316595
316456
  logError2(new Error("Windows NPM detected in WSL environment"));
316596
316457
  logEvent("tengu_auto_updater_windows_npm_in_wsl", {
316597
- currentVersion: "1.65.10"
316458
+ currentVersion: "1.65.12"
316598
316459
  });
316599
316460
  console.error(`
316600
316461
  Error: Windows NPM detected in WSL
@@ -317129,7 +316990,7 @@ function detectLinuxGlobPatternWarnings() {
317129
316990
  }
317130
316991
  async function getDoctorDiagnostic() {
317131
316992
  const installationType = await getCurrentInstallationType();
317132
- const version2 = typeof MACRO !== "undefined" ? "1.65.10" : "unknown";
316993
+ const version2 = typeof MACRO !== "undefined" ? "1.65.12" : "unknown";
317133
316994
  const installationPath = await getInstallationPath();
317134
316995
  const invokedBinary = getInvokedBinary();
317135
316996
  const multipleInstallations = await detectMultipleInstallations();
@@ -318064,8 +317925,8 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
318064
317925
  const maxVersion = await getMaxVersion();
318065
317926
  if (maxVersion && gt(version2, maxVersion)) {
318066
317927
  logForDebugging(`Native installer: maxVersion ${maxVersion} is set, capping update from ${version2} to ${maxVersion}`);
318067
- if (gte("1.65.10", maxVersion)) {
318068
- logForDebugging(`Native installer: current version ${"1.65.10"} is already at or above maxVersion ${maxVersion}, skipping update`);
317928
+ if (gte("1.65.12", maxVersion)) {
317929
+ logForDebugging(`Native installer: current version ${"1.65.12"} is already at or above maxVersion ${maxVersion}, skipping update`);
318069
317930
  logEvent("tengu_native_update_skipped_max_version", {
318070
317931
  latency_ms: Date.now() - startTime,
318071
317932
  max_version: maxVersion,
@@ -318076,7 +317937,7 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
318076
317937
  version2 = maxVersion;
318077
317938
  }
318078
317939
  }
318079
- if (!forceReinstall && version2 === "1.65.10" && await versionIsAvailable(version2) && await isPossibleURBinary(executablePath)) {
317940
+ if (!forceReinstall && version2 === "1.65.12" && await versionIsAvailable(version2) && await isPossibleURBinary(executablePath)) {
318080
317941
  logForDebugging(`Found ${version2} at ${executablePath}, skipping install`);
318081
317942
  logEvent("tengu_native_update_complete", {
318082
317943
  latency_ms: Date.now() - startTime,
@@ -361148,7 +361009,7 @@ Usage:${getPreReadInstruction2()}
361148
361009
  - When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: ${prefixFormat}. Everything after that is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string.
361149
361010
  - ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
361150
361011
  - Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.
361151
- - \`old_string\` must be copied from the current file as one exact, contiguous block. If it is not found, re-read the target region and retry with a corrected smaller block; never retry the unchanged call.
361012
+ - \`old_string\` must be copied from a recent Read of the target file as one exact, contiguous block. Never reconstruct it from memory, from an earlier full-file Write, or from what you expected the file to contain. If it is not found, re-read the target region and retry with a corrected smaller block; never retry the unchanged call.
361152
361013
  - The edit will FAIL if \`old_string\` is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use \`replace_all\` to change every instance of \`old_string\`.${minimalUniquenessHint}
361153
361014
  - Use \`replace_all\` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.`;
361154
361015
  }
@@ -361192,6 +361053,7 @@ var init_types11 = __esm(() => {
361192
361053
  structuredPatch: exports_external.array(hunkSchema()).describe("Diff patch showing the changes"),
361193
361054
  userModified: exports_external.boolean().describe("Whether the user modified the proposed changes"),
361194
361055
  replaceAll: exports_external.boolean().describe("Whether all occurrences were replaced"),
361056
+ alreadyApplied: exports_external.boolean().optional().describe("Whether the requested deletion-only replacement was already present and no write was needed"),
361195
361057
  gitDiff: gitDiffSchema().optional()
361196
361058
  }));
361197
361059
  });
@@ -363543,30 +363405,48 @@ function findSearchAnchor(fileContent, searchString) {
363543
363405
  occurrencesByLine.set(normalized, { firstIndex: index2, count: 1 });
363544
363406
  }
363545
363407
  }
363546
- let repeatedMatch = null;
363547
- for (const searchLine of searchString.split(`
363548
- `)) {
363408
+ const candidates = [];
363409
+ const searchLines = searchString.split(`
363410
+ `);
363411
+ for (let searchIndex = 0;searchIndex < searchLines.length; searchIndex++) {
363412
+ const searchLine = searchLines[searchIndex];
363549
363413
  const normalized = normalizeLineForMatch(searchLine);
363550
363414
  if (normalized.trim().length === 0)
363551
363415
  continue;
363552
363416
  const occurrence = occurrencesByLine.get(normalized);
363553
363417
  if (!occurrence)
363554
363418
  continue;
363555
- if (occurrence.count === 1) {
363556
- return { fileLine: occurrence.firstIndex + 1, unique: true };
363557
- }
363558
- repeatedMatch ??= {
363419
+ candidates.push({
363559
363420
  fileLine: occurrence.firstIndex + 1,
363560
- unique: false
363561
- };
363421
+ unique: occurrence.count === 1,
363422
+ searchLine: normalized,
363423
+ searchLineNumber: searchIndex + 1,
363424
+ occurrenceCount: occurrence.count,
363425
+ distinctiveCharacterCount: normalized.replace(/[^A-Za-z0-9_$]/g, "").length
363426
+ });
363562
363427
  }
363563
- return repeatedMatch;
363428
+ candidates.sort((left, right) => {
363429
+ if (left.unique !== right.unique)
363430
+ return left.unique ? -1 : 1;
363431
+ if (left.occurrenceCount !== right.occurrenceCount) {
363432
+ return left.occurrenceCount - right.occurrenceCount;
363433
+ }
363434
+ if (left.distinctiveCharacterCount !== right.distinctiveCharacterCount) {
363435
+ return right.distinctiveCharacterCount - left.distinctiveCharacterCount;
363436
+ }
363437
+ if (left.searchLine.length !== right.searchLine.length) {
363438
+ return right.searchLine.length - left.searchLine.length;
363439
+ }
363440
+ return left.searchLineNumber - right.searchLineNumber;
363441
+ });
363442
+ return candidates[0] ?? null;
363564
363443
  }
363565
363444
  function formatStringNotFoundMessage(fileContent, searchString) {
363566
363445
  const lineCount = searchString.split(`
363567
363446
  `).length;
363568
363447
  const anchor = findSearchAnchor(fileContent, searchString);
363569
- const location = anchor ? `A line from old_string ${anchor.unique ? "uniquely " : ""}matches the current file at line ${anchor.fileLine}, but the complete ${lineCount}-line block is not contiguous there.` : "No complete non-empty line from old_string matches the current file.";
363448
+ const anchorPreview = anchor ? JSON.stringify(anchor.searchLine.length > 160 ? `${anchor.searchLine.slice(0, 160)}\u2026` : anchor.searchLine) : null;
363449
+ const location = anchor ? `The verified anchor ${anchorPreview} from old_string line ${anchor.searchLineNumber} ${anchor.unique ? "uniquely " : ""}matches the current file at line ${anchor.fileLine}, but the complete ${lineCount}-line block is not contiguous there.` : "No complete non-empty line from old_string matches the current file.";
363570
363450
  const recovery = anchor ? `Re-read the target around line ${anchor.fileLine}, then retry with the smallest unique contiguous old_string copied from the current Read output (usually 2-4 lines).` : "Search for a short distinctive fragment, re-read the current target region, then retry with the smallest unique contiguous old_string (usually 2-4 lines).";
363571
363451
  const preview = searchString.length > STRING_NOT_FOUND_PREVIEW_CHARS ? `${searchString.slice(0, STRING_NOT_FOUND_PREVIEW_CHARS)}
363572
363452
  \u2026 [old_string preview truncated; ${searchString.length} characters total]` : searchString;
@@ -363592,6 +363472,15 @@ function findActualString(fileContent, searchString) {
363592
363472
  }
363593
363473
  return findActualStringWhitespaceTolerant(fileContent, searchString);
363594
363474
  }
363475
+ function isDeletionOnlyEditAlreadyApplied(fileContent, oldString, newString, replaceAll) {
363476
+ if (replaceAll || oldString.length === 0 || newString.length === 0 || oldString === newString || !oldString.includes(newString) || findActualString(fileContent, oldString) !== null) {
363477
+ return false;
363478
+ }
363479
+ const actualNewString = findActualString(fileContent, newString);
363480
+ if (actualNewString === null)
363481
+ return false;
363482
+ return fileContent.split(actualNewString).length - 1 === 1;
363483
+ }
363595
363484
  function preserveQuoteStyle(oldString, actualOldString, newString) {
363596
363485
  if (oldString === actualOldString) {
363597
363486
  return newString;
@@ -363967,11 +363856,20 @@ function renderToolUseMessage9({
363967
363856
  function renderToolResultMessage8({
363968
363857
  filePath,
363969
363858
  structuredPatch: structuredPatch2,
363970
- originalFile
363859
+ originalFile,
363860
+ alreadyApplied
363971
363861
  }, _progressMessagesForMessage, {
363972
363862
  style,
363973
363863
  verbose
363974
363864
  }) {
363865
+ if (alreadyApplied) {
363866
+ return /* @__PURE__ */ jsx_dev_runtime132.jsxDEV(MessageResponse, {
363867
+ children: /* @__PURE__ */ jsx_dev_runtime132.jsxDEV(ThemedText, {
363868
+ dimColor: true,
363869
+ children: "Already up to date"
363870
+ }, undefined, false, undefined, this)
363871
+ }, undefined, false, undefined, this);
363872
+ }
363975
363873
  const isPlanFile = filePath.startsWith(getPlansDirectory());
363976
363874
  return /* @__PURE__ */ jsx_dev_runtime132.jsxDEV(FileEditToolUpdatedMessage, {
363977
363875
  filePath,
@@ -364447,6 +364345,9 @@ var init_FileEditTool = __esm(() => {
364447
364345
  const file2 = fileContent;
364448
364346
  const actualOldString = findActualString(file2, old_string);
364449
364347
  if (!actualOldString) {
364348
+ if (isDeletionOnlyEditAlreadyApplied(file2, old_string, new_string, replace_all)) {
364349
+ return { result: true };
364350
+ }
364450
364351
  return {
364451
364352
  result: false,
364452
364353
  behavior: "ask",
@@ -364510,6 +364411,27 @@ String: ${old_string}`,
364510
364411
  const { file_path, old_string, new_string, replace_all = false } = input;
364511
364412
  const fs4 = getFsImplementation();
364512
364413
  const absoluteFilePath = expandPath(file_path);
364414
+ const initialState = readFileForEdit(absoluteFilePath);
364415
+ if (initialState.fileExists) {
364416
+ const lastRead = readFileState.get(absoluteFilePath);
364417
+ if (!lastRead || getFileModificationTime(absoluteFilePath) > lastRead.timestamp || !fileStateMatchesContent(initialState.content, lastRead)) {
364418
+ throw new Error(FILE_UNEXPECTEDLY_MODIFIED_ERROR);
364419
+ }
364420
+ if (isDeletionOnlyEditAlreadyApplied(initialState.content, old_string, new_string, replace_all)) {
364421
+ return {
364422
+ data: {
364423
+ filePath: file_path,
364424
+ oldString: old_string,
364425
+ newString: new_string,
364426
+ originalFile: initialState.content,
364427
+ structuredPatch: [],
364428
+ userModified: userModified ?? false,
364429
+ replaceAll: replace_all,
364430
+ alreadyApplied: true
364431
+ }
364432
+ };
364433
+ }
364434
+ }
364513
364435
  const cwd2 = getCwd();
364514
364436
  if (!isEnvTruthy(process.env.UR_CODE_SIMPLE)) {
364515
364437
  const newSkillDirs = await discoverSkillDirsForPaths([absoluteFilePath], cwd2);
@@ -364627,7 +364549,14 @@ String: ${old_string}`,
364627
364549
  };
364628
364550
  },
364629
364551
  mapToolResultToToolResultBlockParam(data, toolUseID) {
364630
- const { filePath, userModified, replaceAll } = data;
364552
+ const { filePath, userModified, replaceAll, alreadyApplied } = data;
364553
+ if (alreadyApplied) {
364554
+ return {
364555
+ tool_use_id: toolUseID,
364556
+ type: "tool_result",
364557
+ content: `The file ${filePath} already contains the requested replacement. No change was needed.`
364558
+ };
364559
+ }
364631
364560
  const modifiedNote = userModified ? ". The user modified your proposed changes before accepting them. " : "";
364632
364561
  if (replaceAll) {
364633
364562
  return {
@@ -373287,6 +373216,21 @@ function TungstenLiveMonitor() {
373287
373216
  }
373288
373217
  var TungstenTool = null;
373289
373218
 
373219
+ // src/utils/zodToJsonSchema.ts
373220
+ function zodToJsonSchema3(schema) {
373221
+ const hit = cache3.get(schema);
373222
+ if (hit)
373223
+ return hit;
373224
+ const result = toJSONSchema(schema);
373225
+ cache3.set(schema, result);
373226
+ return result;
373227
+ }
373228
+ var cache3;
373229
+ var init_zodToJsonSchema2 = __esm(() => {
373230
+ init_v4();
373231
+ cache3 = new WeakMap;
373232
+ });
373233
+
373290
373234
  // src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx
373291
373235
  function objectValue3(value) {
373292
373236
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -373306,81 +373250,108 @@ function stringField2(input, names) {
373306
373250
  }
373307
373251
  function normalizeQuestionOptionInput(value) {
373308
373252
  if (typeof value === "string") {
373309
- const label2 = value.trim();
373310
- return label2 ? {
373311
- label: label2,
373312
- description: label2
373253
+ const label = value.trim();
373254
+ return label ? {
373255
+ label
373313
373256
  } : value;
373314
373257
  }
373315
373258
  const option = objectValue3(value);
373316
373259
  if (!option)
373317
373260
  return value;
373318
- const label = typeof option.label === "string" && option.label.trim() ? option.label.trim() : typeof option.value === "string" && option.value.trim() ? option.value.trim() : typeof option.description === "string" && option.description.trim() ? option.description.trim() : "";
373319
- const description = typeof option.description === "string" && option.description.trim() ? option.description.trim() : label;
373320
- if (!label || !description)
373321
- return value;
373322
- return {
373323
- label,
373324
- description,
373325
- ...typeof option.preview === "string" ? {
373326
- preview: option.preview
373327
- } : {}
373328
- };
373261
+ const normalized = { ...option };
373262
+ if (typeof option.label === "string")
373263
+ normalized.label = option.label.trim();
373264
+ if (typeof option.description === "string")
373265
+ normalized.description = option.description.trim();
373266
+ if (typeof option.preview === "string")
373267
+ normalized.preview = normalizePreviewInput(option.preview);
373268
+ return normalized;
373269
+ }
373270
+ function normalizePreviewInput(preview) {
373271
+ if (getQuestionPreviewFormat() !== "html")
373272
+ return preview;
373273
+ const alreadySafe = preview.match(/^<pre data-ur-preview="text">([\s\S]*)<\/pre>$/);
373274
+ if (alreadySafe && !alreadySafe[1]?.includes("<"))
373275
+ return preview;
373276
+ const escaped = preview.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
373277
+ return `<pre data-ur-preview="text">${escaped}</pre>`;
373329
373278
  }
373330
373279
  function normalizeQuestionInput(value, index2) {
373331
373280
  const question = objectValue3(value);
373332
- if (!question || !Array.isArray(question.options))
373333
- return value;
373334
- const questionText = stringField2(question, ["question", "questionText", "question_text", "prompt", "text", "title", "message", "body"]);
373335
- if (!questionText)
373281
+ if (!question)
373336
373282
  return value;
373337
- return {
373338
- question: questionText,
373339
- header: typeof question.header === "string" && question.header.trim() ? question.header.trim().slice(0, ASK_USER_QUESTION_TOOL_CHIP_WIDTH) : headerFromQuestion2(questionText, index2),
373340
- options: question.options.map(normalizeQuestionOptionInput),
373341
- ...typeof question.multiSelect === "boolean" ? {
373342
- multiSelect: question.multiSelect
373343
- } : {}
373344
- };
373283
+ const normalized = { ...question };
373284
+ const questionText = stringField2(question, [...QUESTION_TEXT_ALIASES]);
373285
+ if (questionText)
373286
+ normalized.question = questionText;
373287
+ for (const alias of QUESTION_TEXT_ALIASES) {
373288
+ if (alias !== "question")
373289
+ delete normalized[alias];
373290
+ }
373291
+ let options2 = question.options;
373292
+ if (options2 === undefined && question.choices !== undefined) {
373293
+ options2 = question.choices;
373294
+ delete normalized.choices;
373295
+ }
373296
+ if (typeof options2 === "string") {
373297
+ const parsed = parseToolInputJsonLenient(options2);
373298
+ if (Array.isArray(parsed))
373299
+ options2 = parsed;
373300
+ }
373301
+ if (Array.isArray(options2)) {
373302
+ normalized.options = options2.map(normalizeQuestionOptionInput);
373303
+ }
373304
+ if (typeof question.header === "string" && question.header.trim()) {
373305
+ normalized.header = question.header.trim();
373306
+ } else if (questionText) {
373307
+ normalized.header = headerFromQuestion2(questionText, index2);
373308
+ }
373309
+ return normalized;
373345
373310
  }
373346
373311
  function normalizeAskUserQuestionInput2(value) {
373347
373312
  const input = objectValue3(value);
373348
373313
  if (!input)
373349
373314
  return value;
373350
- const commonFields = {
373351
- ...objectValue3(input.answers) ? {
373352
- answers: input.answers
373353
- } : {},
373354
- ...objectValue3(input.annotations) ? {
373355
- annotations: input.annotations
373356
- } : {},
373357
- ...objectValue3(input.metadata) ? {
373358
- metadata: input.metadata
373359
- } : {}
373360
- };
373361
- if (typeof input.questions === "string") {
373362
- const parsed = parseToolInputJsonLenient(input.questions);
373315
+ const normalized = { ...input };
373316
+ let questions = input.questions;
373317
+ if (typeof questions === "string") {
373318
+ const parsed = parseToolInputJsonLenient(questions);
373363
373319
  if (Array.isArray(parsed))
373364
- input.questions = parsed;
373320
+ questions = parsed;
373365
373321
  }
373366
- if (typeof input.options === "string") {
373367
- const parsed = parseToolInputJsonLenient(input.options);
373368
- if (Array.isArray(parsed))
373369
- input.options = parsed;
373322
+ if (Array.isArray(questions)) {
373323
+ normalized.questions = questions.map(normalizeQuestionInput);
373324
+ return normalized;
373370
373325
  }
373371
- if (Array.isArray(input.questions)) {
373372
- return {
373373
- questions: input.questions.map(normalizeQuestionInput),
373374
- ...commonFields
373375
- };
373326
+ let options2 = input.options;
373327
+ if (typeof options2 === "string") {
373328
+ const parsed = parseToolInputJsonLenient(options2);
373329
+ if (Array.isArray(parsed))
373330
+ options2 = parsed;
373376
373331
  }
373377
- if (typeof input.question === "string" && Array.isArray(input.options)) {
373332
+ if (stringField2(input, [...QUESTION_TEXT_ALIASES]) && Array.isArray(options2)) {
373333
+ const singleQuestion = normalizeQuestionInput({
373334
+ question: stringField2(input, [...QUESTION_TEXT_ALIASES]),
373335
+ ...input.header !== undefined ? {
373336
+ header: input.header
373337
+ } : {},
373338
+ options: options2,
373339
+ ...input.multiSelect !== undefined ? {
373340
+ multiSelect: input.multiSelect
373341
+ } : {}
373342
+ }, 0);
373343
+ for (const key of [...QUESTION_TEXT_ALIASES, "header", "options", "choices", "multiSelect"]) {
373344
+ delete normalized[key];
373345
+ }
373378
373346
  return {
373379
- questions: [normalizeQuestionInput(input, 0)],
373380
- ...commonFields
373347
+ ...normalized,
373348
+ questions: [singleQuestion]
373381
373349
  };
373382
373350
  }
373383
- return value;
373351
+ return normalized;
373352
+ }
373353
+ function boundedText(max2, field) {
373354
+ return exports_external.string().trim().min(1, `${field} cannot be empty`).max(max2, `${field} must be at most ${max2} characters`).refine((value) => !CONTROL_OR_ANSI_RE.test(value), `${field} must not contain control or ANSI escape characters`);
373384
373355
  }
373385
373356
  function AskUserQuestionResultMessage(t0) {
373386
373357
  const $2 = import_compiler_runtime114.c(3);
@@ -373445,18 +373416,15 @@ function _temp51(t0) {
373445
373416
  function validateHtmlPreview(preview) {
373446
373417
  if (preview === undefined)
373447
373418
  return null;
373448
- if (/<\s*(html|body|!doctype)\b/i.test(preview)) {
373449
- return "preview must be an HTML fragment, not a full document (no <html>, <body>, or <!DOCTYPE>)";
373450
- }
373451
- if (/<\s*(script|style)\b/i.test(preview)) {
373452
- return "preview must not contain <script> or <style> tags. Use inline styles via the style attribute if needed.";
373453
- }
373454
- if (!/<[a-z][^>]*>/i.test(preview)) {
373455
- return 'preview must contain HTML (previewFormat is set to "html"). Wrap content in a tag like <div> or <pre>.';
373419
+ if (getQuestionPreviewFormat() !== "html")
373420
+ return null;
373421
+ const safeTextWrapper = preview.match(/^<pre data-ur-preview="text">([\s\S]*)<\/pre>$/);
373422
+ if (!safeTextWrapper || safeTextWrapper[1]?.includes("<")) {
373423
+ return "HTML previews must use UR\u2019s escaped text wrapper; raw model-provided HTML is not rendered";
373456
373424
  }
373457
373425
  return null;
373458
373426
  }
373459
- var import_compiler_runtime114, jsx_dev_runtime145, questionOptionSchema, questionSchema, annotationsSchema, UNIQUENESS_REFINE, commonFields, inputSchema32, outputSchema27, AskUserQuestionTool;
373427
+ var import_compiler_runtime114, jsx_dev_runtime145, MAX_QUESTIONS = 4, MAX_OPTIONS = 8, MAX_QUESTION_CHARS = 500, MAX_LABEL_CHARS = 80, MAX_DESCRIPTION_CHARS = 500, MAX_PREVIEW_CHARS, MAX_PREVIEW_LINES = 200, MAX_ANSWER_CHARS = 2000, MAX_TOTAL_INPUT_CHARS, RESERVED_RECORD_KEYS, QUESTION_TEXT_ALIASES, CONTROL_OR_ANSI_RE, UNIQUENESS_REFINE, questionOptionSchema, questionSchema, annotationsSchema, responseFields, metadataSchema, requestObjectSchema, inputSchema32, modelInputJSONSchema, outputSchema27, AskUserQuestionTool;
373460
373428
  var init_AskUserQuestionTool = __esm(() => {
373461
373429
  init_state();
373462
373430
  init_MessageResponse();
@@ -373466,59 +373434,82 @@ var init_AskUserQuestionTool = __esm(() => {
373466
373434
  init_v4();
373467
373435
  init_ink2();
373468
373436
  init_Tool();
373437
+ init_zodToJsonSchema2();
373469
373438
  init_prompt9();
373470
373439
  import_compiler_runtime114 = __toESM(require_compiler_runtime(), 1);
373471
373440
  jsx_dev_runtime145 = __toESM(require_jsx_dev_runtime(), 1);
373472
- questionOptionSchema = lazySchema(() => exports_external.object({
373473
- label: exports_external.string().describe('The choice itself, 1-5 words. Name the option, do not restate the question: for "Which database?" use "PostgreSQL", not "Use PostgreSQL for the database".'),
373474
- description: exports_external.string().describe('What actually happens if this is chosen, and the cost of choosing it \u2014 the information the user needs that the label does not already give them. Must NOT restate the label in a full sentence. Bad: label "PostgreSQL" / description "Use PostgreSQL." Good: label "PostgreSQL" / description "Relational, strong consistency; needs a running server and a migration step." Include the trade-off, limitation, or consequence that makes this choice different from the others.'),
373475
- preview: exports_external.string().optional().describe("Optional preview content rendered when this option is focused. Use for mockups, code snippets, or visual comparisons that help users compare options. See the tool description for the expected content format.")
373476
- }));
373477
- questionSchema = lazySchema(() => exports_external.object({
373478
- question: exports_external.string().describe('The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"'),
373479
- header: exports_external.string().describe(`The category being decided, as a chip/tag (max ${ASK_USER_QUESTION_TOOL_CHIP_WIDTH} chars). Name the dimension, not the question: for "Which database should we use?" the header is "Database", not "Which DB". Examples: "Auth method", "Library", "Approach".`),
373480
- options: exports_external.array(questionOptionSchema()).min(2).max(8).describe(`REQUIRED: 2-8 concrete choices. A question with no options is not askable here \u2014 if you cannot name at least two specific answers, the question is open-ended, so ask it in plain assistant text instead of calling this tool. Do not call this tool with a prose question and omit options. Keep options concise and distinct; there should be no 'Other' option, that will be provided automatically.`),
373481
- multiSelect: exports_external.boolean().default(false).describe("Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive.")
373482
- }));
373483
- annotationsSchema = lazySchema(() => {
373484
- const annotationSchema = exports_external.object({
373485
- preview: exports_external.string().optional().describe("The preview content of the selected option, if the question used previews."),
373486
- notes: exports_external.string().optional().describe("Free-text notes the user added to their selection.")
373487
- });
373488
- return exports_external.record(exports_external.string(), annotationSchema).optional().describe("Optional per-question annotations from the user (e.g., notes on preview selections). Keyed by question text.");
373489
- });
373441
+ MAX_PREVIEW_CHARS = 16 * 1024;
373442
+ MAX_TOTAL_INPUT_CHARS = 64 * 1024;
373443
+ RESERVED_RECORD_KEYS = new Set(["__proto__", "constructor", "prototype", "toString", "valueOf"]);
373444
+ QUESTION_TEXT_ALIASES = ["question", "questionText", "question_text", "prompt", "text"];
373445
+ CONTROL_OR_ANSI_RE = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]|\u001B\[/;
373490
373446
  UNIQUENESS_REFINE = {
373491
373447
  check: (data) => {
373492
- const questions = data.questions.map((q) => q.question);
373448
+ const questions = data.questions.map((q) => q.question.toLocaleLowerCase());
373493
373449
  if (questions.length !== new Set(questions).size) {
373494
373450
  return false;
373495
373451
  }
373496
373452
  for (const question of data.questions) {
373497
- const labels = question.options.map((opt) => opt.label);
373453
+ const labels = question.options.map((opt) => opt.label.toLocaleLowerCase());
373498
373454
  if (labels.length !== new Set(labels).size) {
373499
373455
  return false;
373500
373456
  }
373501
373457
  }
373502
373458
  return true;
373503
373459
  },
373504
- message: "Question texts must be unique, option labels must be unique within each question"
373460
+ message: "Question texts must be unique, and option labels must be unique within each question (ignoring case)"
373505
373461
  };
373506
- commonFields = lazySchema(() => ({
373507
- answers: exports_external.record(exports_external.string(), exports_external.string()).optional().describe("User answers collected by the permission component"),
373508
- annotations: annotationsSchema(),
373509
- metadata: exports_external.object({
373510
- source: exports_external.string().optional().describe('Optional identifier for the source of this question (e.g., "remember" for /remember command). Used for analytics tracking.')
373511
- }).optional().describe("Optional metadata for tracking and analytics purposes. Not displayed to user.")
373462
+ questionOptionSchema = lazySchema(() => exports_external.strictObject({
373463
+ label: boundedText(MAX_LABEL_CHARS, "Option label").refine((label) => {
373464
+ const normalized = label.trim().toLocaleLowerCase();
373465
+ return normalized !== "other" && normalized !== "__other__";
373466
+ }, "Do not provide an Other option; the UI supplies it automatically.").describe("The concise name of this choice, usually 1-5 words. It must be distinct from every other label in this question."),
373467
+ description: boundedText(MAX_DESCRIPTION_CHARS, "Option description").optional().describe("Optional consequence, trade-off, or limitation that adds information beyond the label. Omit it when there is nothing useful to add; never duplicate the label merely to fill this field."),
373468
+ preview: exports_external.string().max(MAX_PREVIEW_CHARS, `Option preview must be at most ${MAX_PREVIEW_CHARS} characters`).refine((value) => value.split(/\r?\n/).length <= MAX_PREVIEW_LINES, `Option preview must be at most ${MAX_PREVIEW_LINES} lines`).optional().describe("Optional bounded preview content rendered when this option is focused.")
373469
+ }));
373470
+ questionSchema = lazySchema(() => exports_external.strictObject({
373471
+ question: boundedText(MAX_QUESTION_CHARS, "Question").refine((question) => !RESERVED_RECORD_KEYS.has(question), "Question text uses a reserved record key; rephrase it.").describe("The complete, specific decision question shown to the user. Ask one decision per object."),
373472
+ header: boundedText(ASK_USER_QUESTION_TOOL_CHIP_WIDTH, "Question header").describe(`A short category chip naming the decision dimension, not a shortened question (max ${ASK_USER_QUESTION_TOOL_CHIP_WIDTH} characters; for \u201CWhich database?\u201D use \u201CDatabase\u201D).`),
373473
+ options: exports_external.array(questionOptionSchema()).min(2).max(MAX_OPTIONS).describe(`REQUIRED: 2-${MAX_OPTIONS} concrete choices nested inside this question object. Do not put option rows directly in the top-level questions array.`),
373474
+ multiSelect: exports_external.boolean().optional().describe("Set to true only when choices are not mutually exclusive. Omit it for ordinary single-select questions.")
373475
+ }).refine((question) => !(question.multiSelect && question.options.some((option) => option.preview !== undefined)), {
373476
+ message: "Preview choices are single-select only; remove previews or set multiSelect to false."
373477
+ }));
373478
+ annotationsSchema = lazySchema(() => {
373479
+ const annotationSchema = exports_external.strictObject({
373480
+ preview: exports_external.string().max(MAX_PREVIEW_CHARS).optional(),
373481
+ notes: exports_external.string().trim().max(MAX_ANSWER_CHARS).optional()
373482
+ });
373483
+ return exports_external.record(exports_external.string(), annotationSchema).optional();
373484
+ });
373485
+ responseFields = lazySchema(() => ({
373486
+ answers: exports_external.record(exports_external.string(), exports_external.string().trim().min(1).max(MAX_ANSWER_CHARS)).optional(),
373487
+ annotations: annotationsSchema()
373488
+ }));
373489
+ metadataSchema = lazySchema(() => exports_external.strictObject({
373490
+ source: exports_external.string().trim().min(1).max(100).optional()
373491
+ }).optional());
373492
+ requestObjectSchema = lazySchema(() => exports_external.strictObject({
373493
+ questions: exports_external.array(questionSchema()).min(1).max(MAX_QUESTIONS).describe(`Questions to ask the user (1-${MAX_QUESTIONS}). Ask only decisions that materially affect the result and cannot be inferred.`),
373494
+ metadata: metadataSchema()
373495
+ }).refine(UNIQUENESS_REFINE.check, {
373496
+ message: UNIQUENESS_REFINE.message
373497
+ }).refine((input) => JSON.stringify(input).length <= MAX_TOTAL_INPUT_CHARS, {
373498
+ message: `AskUserQuestion input must be at most ${MAX_TOTAL_INPUT_CHARS} characters`
373512
373499
  }));
373513
373500
  inputSchema32 = lazySchema(() => exports_external.preprocess(normalizeAskUserQuestionInput2, exports_external.strictObject({
373514
- questions: exports_external.array(questionSchema()).min(1).max(4).describe("Questions to ask the user (1-4 questions)"),
373515
- ...commonFields()
373501
+ questions: exports_external.array(questionSchema()).min(1).max(MAX_QUESTIONS),
373502
+ metadata: metadataSchema(),
373503
+ ...responseFields()
373516
373504
  }).refine(UNIQUENESS_REFINE.check, {
373517
373505
  message: UNIQUENESS_REFINE.message
373506
+ }).refine((input) => JSON.stringify(input).length <= MAX_TOTAL_INPUT_CHARS, {
373507
+ message: `AskUserQuestion input must be at most ${MAX_TOTAL_INPUT_CHARS} characters`
373518
373508
  })));
373519
- outputSchema27 = lazySchema(() => exports_external.object({
373509
+ modelInputJSONSchema = zodToJsonSchema3(requestObjectSchema());
373510
+ outputSchema27 = lazySchema(() => exports_external.strictObject({
373520
373511
  questions: exports_external.array(questionSchema()).describe("The questions that were asked"),
373521
- answers: exports_external.record(exports_external.string(), exports_external.string()).describe("The answers provided by the user (question text -> answer string; multi-select answers are comma-separated)"),
373512
+ answers: exports_external.record(exports_external.string(), exports_external.string().trim().min(1).max(MAX_ANSWER_CHARS)).describe("The answers provided by the user (question text -> answer string; multi-select answers are comma-separated)"),
373522
373513
  annotations: annotationsSchema()
373523
373514
  }));
373524
373515
  AskUserQuestionTool = buildTool({
@@ -373539,6 +373530,7 @@ var init_AskUserQuestionTool = __esm(() => {
373539
373530
  get inputSchema() {
373540
373531
  return inputSchema32();
373541
373532
  },
373533
+ inputJSONSchema: modelInputJSONSchema,
373542
373534
  get outputSchema() {
373543
373535
  return outputSchema27();
373544
373536
  },
@@ -373561,14 +373553,10 @@ var init_AskUserQuestionTool = __esm(() => {
373561
373553
  requiresUserInteraction() {
373562
373554
  return true;
373563
373555
  },
373564
- async validateInput({
373565
- questions
373566
- }) {
373567
- if (getQuestionPreviewFormat() !== "html") {
373568
- return {
373569
- result: true
373570
- };
373571
- }
373556
+ async validateInput(input, context5) {
373557
+ const {
373558
+ questions
373559
+ } = input;
373572
373560
  for (const q of questions) {
373573
373561
  for (const opt of q.options) {
373574
373562
  const err2 = validateHtmlPreview(opt.preview);
@@ -373581,6 +373569,45 @@ var init_AskUserQuestionTool = __esm(() => {
373581
373569
  }
373582
373570
  }
373583
373571
  }
373572
+ if (context5.validationPhase !== "post-permission") {
373573
+ if (Object.prototype.hasOwnProperty.call(input, "answers") || Object.prototype.hasOwnProperty.call(input, "annotations")) {
373574
+ return {
373575
+ result: false,
373576
+ message: "answers and annotations are response fields supplied only after trusted user interaction; omit them from the tool request",
373577
+ errorCode: 1
373578
+ };
373579
+ }
373580
+ return {
373581
+ result: true
373582
+ };
373583
+ }
373584
+ if (!Object.prototype.hasOwnProperty.call(input, "answers") || !input.answers) {
373585
+ return {
373586
+ result: false,
373587
+ message: "No verified user answers were collected. AskUserQuestion cannot complete from an unchanged permission approval.",
373588
+ errorCode: 1
373589
+ };
373590
+ }
373591
+ const expectedQuestions = new Set(questions.map((question) => question.question));
373592
+ const answerKeys = Object.keys(input.answers);
373593
+ const missingAnswers = questions.filter((question) => !Object.prototype.hasOwnProperty.call(input.answers, question.question)).map((question) => question.question);
373594
+ const unexpectedAnswers = answerKeys.filter((key) => !expectedQuestions.has(key));
373595
+ if (missingAnswers.length > 0 || unexpectedAnswers.length > 0) {
373596
+ const details = [...missingAnswers.length > 0 ? [`missing: ${missingAnswers.join(", ")}`] : [], ...unexpectedAnswers.length > 0 ? [`unexpected: ${unexpectedAnswers.join(", ")}`] : []].join("; ");
373597
+ return {
373598
+ result: false,
373599
+ message: `Verified answers must contain exactly one entry for every question (${details}).`,
373600
+ errorCode: 1
373601
+ };
373602
+ }
373603
+ const unexpectedAnnotations = Object.keys(input.annotations ?? {}).filter((key) => !expectedQuestions.has(key));
373604
+ if (unexpectedAnnotations.length > 0) {
373605
+ return {
373606
+ result: false,
373607
+ message: `User annotations contain unknown question keys: ${unexpectedAnnotations.join(", ")}`,
373608
+ errorCode: 1
373609
+ };
373610
+ }
373584
373611
  return {
373585
373612
  result: true
373586
373613
  };
@@ -373628,9 +373655,12 @@ var init_AskUserQuestionTool = __esm(() => {
373628
373655
  },
373629
373656
  async call({
373630
373657
  questions,
373631
- answers = {},
373658
+ answers,
373632
373659
  annotations
373633
373660
  }, _context) {
373661
+ if (!answers) {
373662
+ throw new Error("AskUserQuestion reached execution without verified user answers");
373663
+ }
373634
373664
  return {
373635
373665
  data: {
373636
373666
  questions,
@@ -375332,10 +375362,10 @@ function DANGEROUS_uncachedSystemPromptSection(name, compute, _reason) {
375332
375362
  return { name, compute, cacheBreak: true };
375333
375363
  }
375334
375364
  async function resolveSystemPromptSections(sections) {
375335
- const cache3 = getSystemPromptSectionCache();
375365
+ const cache4 = getSystemPromptSectionCache();
375336
375366
  return Promise.all(sections.map(async (s) => {
375337
- if (!s.cacheBreak && cache3.has(s.name)) {
375338
- return cache3.get(s.name) ?? null;
375367
+ if (!s.cacheBreak && cache4.has(s.name)) {
375368
+ return cache4.get(s.name) ?? null;
375339
375369
  }
375340
375370
  const value = await s.compute();
375341
375371
  setSystemPromptSectionCacheEntry(s.name, value);
@@ -377993,6 +378023,117 @@ var init_TaskGetTool = __esm(() => {
377993
378023
  });
377994
378024
  });
377995
378025
 
378026
+ // src/tools/TaskUpdateTool/completionEvidence.ts
378027
+ function messageBlocks(message) {
378028
+ const content = message.message?.content;
378029
+ return Array.isArray(content) ? content : [];
378030
+ }
378031
+ function successfulCalls(messages) {
378032
+ if (!Array.isArray(messages))
378033
+ return [];
378034
+ const toolUses = new Map;
378035
+ const calls = [];
378036
+ let sequence = 0;
378037
+ for (const [messageIndex, candidate] of messages.entries()) {
378038
+ if (typeof candidate !== "object" || candidate === null)
378039
+ continue;
378040
+ const message = candidate;
378041
+ for (const block2 of messageBlocks(message)) {
378042
+ sequence++;
378043
+ if (typeof block2 !== "object" || block2 === null)
378044
+ continue;
378045
+ const value = block2;
378046
+ if (value.type === "tool_use" && typeof value.id === "string" && typeof value.name === "string") {
378047
+ toolUses.set(value.id, {
378048
+ name: value.name,
378049
+ input: typeof value.input === "object" && value.input !== null ? value.input : {},
378050
+ sequence,
378051
+ assistantMessage: messageIndex
378052
+ });
378053
+ continue;
378054
+ }
378055
+ if (value.type !== "tool_result" || typeof value.tool_use_id !== "string") {
378056
+ continue;
378057
+ }
378058
+ const toolUse = toolUses.get(value.tool_use_id);
378059
+ if (!toolUse)
378060
+ continue;
378061
+ calls.push({
378062
+ ...toolUse,
378063
+ succeeded: value.is_error !== true
378064
+ });
378065
+ }
378066
+ }
378067
+ return calls.sort((left, right) => left.sequence - right.sequence);
378068
+ }
378069
+ function sameTaskId(value, taskId) {
378070
+ return (typeof value === "string" || typeof value === "number") && String(value) === taskId;
378071
+ }
378072
+ function mutationTarget(call6) {
378073
+ for (const key of ["file_path", "notebook_path", "path"]) {
378074
+ const value = call6.input[key];
378075
+ if (typeof value === "string" && value.trim() !== "")
378076
+ return value;
378077
+ }
378078
+ return;
378079
+ }
378080
+ function evaluateCompletionEvidence(input) {
378081
+ const calls = successfulCalls(input.messages);
378082
+ let startedAt = -1;
378083
+ for (const call6 of calls) {
378084
+ if (call6.succeeded && call6.name === "TaskUpdate" && sameTaskId(call6.input.taskId, input.taskId) && call6.input.status === "in_progress") {
378085
+ startedAt = call6.sequence;
378086
+ }
378087
+ }
378088
+ if (startedAt < 0)
378089
+ return { defer: false };
378090
+ let latestMutation;
378091
+ let hasEvidenceAfterMutation = false;
378092
+ for (const call6 of calls) {
378093
+ if (!call6.succeeded || call6.sequence <= startedAt)
378094
+ continue;
378095
+ if (FILE_MUTATION_TOOLS.has(call6.name)) {
378096
+ latestMutation = call6;
378097
+ hasEvidenceAfterMutation = false;
378098
+ continue;
378099
+ }
378100
+ if (latestMutation && call6.assistantMessage > latestMutation.assistantMessage && COMPLETION_EVIDENCE_TOOLS.has(call6.name)) {
378101
+ hasEvidenceAfterMutation = true;
378102
+ }
378103
+ }
378104
+ if (!latestMutation || hasEvidenceAfterMutation) {
378105
+ return { defer: false };
378106
+ }
378107
+ return {
378108
+ defer: true,
378109
+ mutationTool: latestMutation.name,
378110
+ target: mutationTarget(latestMutation)
378111
+ };
378112
+ }
378113
+ var FILE_MUTATION_TOOLS, COMPLETION_EVIDENCE_TOOLS;
378114
+ var init_completionEvidence = __esm(() => {
378115
+ FILE_MUTATION_TOOLS = new Set([
378116
+ "Write",
378117
+ "Edit",
378118
+ "MultiEdit",
378119
+ "NotebookEdit"
378120
+ ]);
378121
+ COMPLETION_EVIDENCE_TOOLS = new Set([
378122
+ "Read",
378123
+ "Grep",
378124
+ "Glob",
378125
+ "LSP",
378126
+ "Bash",
378127
+ "PowerShell",
378128
+ "TestRunner",
378129
+ "Browser",
378130
+ "Computer",
378131
+ "TaskOutput",
378132
+ "Agent",
378133
+ "Task"
378134
+ ]);
378135
+ });
378136
+
377996
378137
  // src/tools/TaskUpdateTool/prompt.ts
377997
378138
  var DESCRIPTION16 = "Update a task in the task list", PROMPT7 = `Use this tool to update a task in the task list.
377998
378139
 
@@ -378004,6 +378145,12 @@ var DESCRIPTION16 = "Update a task in the task list", PROMPT7 = `Use this tool t
378004
378145
  - After completion, call TaskList to find the next unblocked task
378005
378146
 
378006
378147
  - ONLY mark a task as completed when you have FULLY accomplished it
378148
+ - After changing a file, run a relevant observable check in a later tool turn
378149
+ before completing the final actionable task. A Write/Edit result proves only
378150
+ that bytes changed, not that the result works.
378151
+ - If that final completion has no successful post-change check, TaskUpdate
378152
+ keeps the same task in_progress and names the next verification action. Run
378153
+ it and retry completion; do not create a duplicate task.
378007
378154
  - If you encounter errors, blockers, or cannot finish, keep the task as in_progress
378008
378155
  - When blocked, record the blocking work as a dependency or notify the owner
378009
378156
  - Never mark a task as completed if:
@@ -378068,6 +378215,7 @@ var init_TaskUpdateTool = __esm(() => {
378068
378215
  init_teammateMailbox();
378069
378216
  init_constants2();
378070
378217
  init_taskIdInput();
378218
+ init_completionEvidence();
378071
378219
  inputSchema40 = lazySchema(() => {
378072
378220
  const TaskUpdateStatusSchema = TaskStatusSchema2().or(exports_external.literal("deleted"));
378073
378221
  const TaskIdSchema = taskIdInputSchema("The ID of the task to update. Positive integer JSON values are accepted and normalized to strings.");
@@ -378092,7 +378240,10 @@ var init_TaskUpdateTool = __esm(() => {
378092
378240
  from: exports_external.string(),
378093
378241
  to: exports_external.string()
378094
378242
  }).optional(),
378095
- verificationNudgeNeeded: exports_external.boolean().optional()
378243
+ verificationNudgeNeeded: exports_external.boolean().optional(),
378244
+ completionDeferred: exports_external.boolean().optional(),
378245
+ completionMutationTool: exports_external.string().optional(),
378246
+ completionVerificationTarget: exports_external.string().optional()
378096
378247
  }));
378097
378248
  TaskUpdateTool = buildTool({
378098
378249
  name: TASK_UPDATE_TOOL_NAME,
@@ -378188,6 +378339,9 @@ var init_TaskUpdateTool = __esm(() => {
378188
378339
  };
378189
378340
  }
378190
378341
  const updatedFields = [];
378342
+ let completionDeferred = false;
378343
+ let completionMutationTool;
378344
+ let completionVerificationTarget;
378191
378345
  const updates = {};
378192
378346
  if (subject !== undefined && subject !== existingTask.subject) {
378193
378347
  updates.subject = subject;
@@ -378258,27 +378412,43 @@ var init_TaskUpdateTool = __esm(() => {
378258
378412
  }
378259
378413
  };
378260
378414
  }
378261
- const blockingErrors = [];
378262
- const generator = executeTaskCompletedHooks(taskId, existingTask.subject, existingTask.description, getAgentName(), getTeamName(), undefined, context5?.abortController?.signal, undefined, context5);
378263
- for await (const result of generator) {
378264
- if (result.blockingError) {
378265
- blockingErrors.push(getTaskCompletedHookMessage(result.blockingError));
378415
+ const otherActionableTasks = [...tasksById.values()].filter((task) => task.id !== taskId && !task.metadata?._internal && (task.status === "pending" || task.status === "in_progress"));
378416
+ if (existingTask.status === "in_progress" && otherActionableTasks.length === 0) {
378417
+ const evidence = evaluateCompletionEvidence({
378418
+ messages: context5.messages,
378419
+ taskId
378420
+ });
378421
+ if (evidence.defer) {
378422
+ completionDeferred = true;
378423
+ completionMutationTool = evidence.mutationTool;
378424
+ completionVerificationTarget = evidence.target;
378425
+ }
378426
+ }
378427
+ if (!completionDeferred) {
378428
+ const blockingErrors = [];
378429
+ const generator = executeTaskCompletedHooks(taskId, existingTask.subject, existingTask.description, getAgentName(), getTeamName(), undefined, context5?.abortController?.signal, undefined, context5);
378430
+ for await (const result of generator) {
378431
+ if (result.blockingError) {
378432
+ blockingErrors.push(getTaskCompletedHookMessage(result.blockingError));
378433
+ }
378266
378434
  }
378267
- }
378268
- if (blockingErrors.length > 0) {
378269
- return {
378270
- data: {
378271
- success: false,
378272
- taskId,
378273
- updatedFields: [],
378274
- error: blockingErrors.join(`
378435
+ if (blockingErrors.length > 0) {
378436
+ return {
378437
+ data: {
378438
+ success: false,
378439
+ taskId,
378440
+ updatedFields: [],
378441
+ error: blockingErrors.join(`
378275
378442
  `)
378276
- }
378277
- };
378443
+ }
378444
+ };
378445
+ }
378278
378446
  }
378279
378447
  }
378280
- updates.status = status;
378281
- updatedFields.push("status");
378448
+ if (!completionDeferred) {
378449
+ updates.status = status;
378450
+ updatedFields.push("status");
378451
+ }
378282
378452
  }
378283
378453
  }
378284
378454
  const newBlocks = (normalizedAddBlocks ?? []).filter((id) => !existingTask.blocks.includes(id));
@@ -378325,7 +378495,10 @@ var init_TaskUpdateTool = __esm(() => {
378325
378495
  taskId,
378326
378496
  updatedFields,
378327
378497
  statusChange: updates.status !== undefined ? { from: existingTask.status, to: updates.status } : undefined,
378328
- verificationNudgeNeeded
378498
+ verificationNudgeNeeded,
378499
+ completionDeferred: completionDeferred || undefined,
378500
+ completionMutationTool,
378501
+ completionVerificationTarget
378329
378502
  }
378330
378503
  };
378331
378504
  },
@@ -378336,7 +378509,10 @@ var init_TaskUpdateTool = __esm(() => {
378336
378509
  updatedFields,
378337
378510
  error: error40,
378338
378511
  statusChange,
378339
- verificationNudgeNeeded
378512
+ verificationNudgeNeeded,
378513
+ completionDeferred,
378514
+ completionMutationTool,
378515
+ completionVerificationTarget
378340
378516
  } = content;
378341
378517
  if (!success2) {
378342
378518
  return {
@@ -378346,6 +378522,14 @@ var init_TaskUpdateTool = __esm(() => {
378346
378522
  is_error: true
378347
378523
  };
378348
378524
  }
378525
+ if (completionDeferred) {
378526
+ const target = completionVerificationTarget ? ` to ${completionVerificationTarget}` : "";
378527
+ return {
378528
+ tool_use_id: toolUseID,
378529
+ type: "tool_result",
378530
+ content: `Task #${taskId} remains in_progress. ` + `${completionMutationTool ?? "A file tool"} made the latest change` + `${target}, but no successful observable check ran afterward. ` + `Run the smallest relevant verification now, fix any failure, then ` + `retry TaskUpdate with status completed. For a browser UI, load it ` + `and inspect runtime/console behavior. Do not create a duplicate ` + `task; this task is still actionable.`
378531
+ };
378532
+ }
378349
378533
  let resultContent = `Updated task #${taskId} ${updatedFields.join(", ")}`;
378350
378534
  if (statusChange?.to === "completed" && getAgentId() && isAgentSwarmsEnabled()) {
378351
378535
  resultContent += `
@@ -387801,7 +387985,7 @@ function isAnyTracingEnabled() {
387801
387985
  return isTelemetryEnabled() || isEnhancedTelemetryEnabled() || isBetaTracingEnabled();
387802
387986
  }
387803
387987
  function getTracer() {
387804
- return import_api39.trace.getTracer("ur-agent.gen_ai", "1.65.10");
387988
+ return import_api39.trace.getTracer("ur-agent.gen_ai", "1.65.12");
387805
387989
  }
387806
387990
  function createSpanAttributes(spanType, customAttributes = {}) {
387807
387991
  const baseAttributes = getTelemetryAttributes();
@@ -388420,9 +388604,129 @@ function formatValidationPath(path14) {
388420
388604
  return index2 === 0 ? segmentStr : `${String(acc)}.${segmentStr}`;
388421
388605
  }, "");
388422
388606
  }
388607
+ function formatList(values2) {
388608
+ const quoted = values2.map((value) => `\`${value}\``);
388609
+ if (quoted.length <= 1)
388610
+ return quoted[0] ?? "";
388611
+ if (quoted.length === 2)
388612
+ return `${quoted[0]} and ${quoted[1]}`;
388613
+ return `${quoted.slice(0, -1).join(", ")}, and ${quoted.at(-1)}`;
388614
+ }
388615
+ function formatIndexSet(indexes) {
388616
+ const sorted = [...new Set(indexes)].sort((a2, b) => a2 - b);
388617
+ if (sorted.length === 0)
388618
+ return "";
388619
+ const contiguous = sorted.every((value, index2) => index2 === 0 || value === sorted[index2 - 1] + 1);
388620
+ if (contiguous && sorted.length > 1) {
388621
+ return `${sorted[0]}..${sorted.at(-1)}`;
388622
+ }
388623
+ return sorted.join(",");
388624
+ }
388625
+ function formatMissingParameterErrors(error40) {
388626
+ const missing = error40.issues.map((issue2, order) => ({ issue: issue2, order })).filter(({ issue: issue2 }) => issue2.code === "invalid_type" && issue2.message.includes("received undefined"));
388627
+ const byPathShape = new Map;
388628
+ for (const { issue: issue2, order } of missing) {
388629
+ const numericAt = issue2.path.findIndex((segment2) => typeof segment2 === "number");
388630
+ if (numericAt === -1 || numericAt === issue2.path.length - 1)
388631
+ continue;
388632
+ const prefix = issue2.path.slice(0, numericAt);
388633
+ const suffix = issue2.path.slice(numericAt + 1);
388634
+ const index2 = issue2.path[numericAt];
388635
+ if (typeof index2 !== "number")
388636
+ continue;
388637
+ const key = JSON.stringify([prefix, suffix]);
388638
+ const group = byPathShape.get(key) ?? {
388639
+ prefix,
388640
+ suffix,
388641
+ indexes: [],
388642
+ issueOrders: [],
388643
+ firstOrder: order
388644
+ };
388645
+ group.indexes.push(index2);
388646
+ group.issueOrders.push(order);
388647
+ byPathShape.set(key, group);
388648
+ }
388649
+ const combined = new Map;
388650
+ for (const group of byPathShape.values()) {
388651
+ const indexes = [...new Set(group.indexes)].sort((a2, b) => a2 - b);
388652
+ if (indexes.length < 2)
388653
+ continue;
388654
+ const key = JSON.stringify([group.prefix, indexes]);
388655
+ const entry = combined.get(key) ?? {
388656
+ prefix: group.prefix,
388657
+ indexes,
388658
+ fields: [],
388659
+ issueOrders: [],
388660
+ firstOrder: group.firstOrder
388661
+ };
388662
+ entry.fields.push(formatValidationPath(group.suffix));
388663
+ entry.issueOrders.push(...group.issueOrders);
388664
+ entry.firstOrder = Math.min(entry.firstOrder, group.firstOrder);
388665
+ combined.set(key, entry);
388666
+ }
388667
+ const lines = [];
388668
+ const consumed = new Set;
388669
+ for (const entry of combined.values()) {
388670
+ const base2 = `${formatValidationPath(entry.prefix)}[${formatIndexSet(entry.indexes)}]`;
388671
+ const fields = [...new Set(entry.fields)];
388672
+ lines.push({
388673
+ order: entry.firstOrder,
388674
+ text: fields.length === 1 ? `The required field ${formatList(fields)} is missing from \`${base2}\`` : `The required fields ${formatList(fields)} are missing from \`${base2}\``
388675
+ });
388676
+ for (const order of entry.issueOrders)
388677
+ consumed.add(order);
388678
+ }
388679
+ for (const { issue: issue2, order } of missing) {
388680
+ if (consumed.has(order))
388681
+ continue;
388682
+ lines.push({
388683
+ order,
388684
+ text: `The required parameter \`${formatValidationPath(issue2.path)}\` is missing`
388685
+ });
388686
+ }
388687
+ return lines.sort((a2, b) => a2.order - b.order).map((line) => line.text);
388688
+ }
388689
+ function formatSizeConstraintErrors(error40) {
388690
+ const result = [];
388691
+ for (const issue2 of error40.issues) {
388692
+ if (issue2.code !== "too_big" && issue2.code !== "too_small")
388693
+ continue;
388694
+ const detail = issue2;
388695
+ const limit = issue2.code === "too_big" ? detail.maximum : detail.minimum;
388696
+ if (limit === undefined) {
388697
+ result.push(issue2.message);
388698
+ continue;
388699
+ }
388700
+ const path14 = formatValidationPath(issue2.path) || "input";
388701
+ const inclusive = detail.inclusive !== false;
388702
+ const comparison = issue2.code === "too_big" ? inclusive ? "at most" : "fewer than" : inclusive ? "at least" : "more than";
388703
+ const unit = detail.origin === "array" ? "items" : detail.origin === "string" ? "characters" : null;
388704
+ result.push(unit ? `The parameter \`${path14}\` must contain ${comparison} ${String(limit)} ${unit}` : `The parameter \`${path14}\` must be ${comparison} ${String(limit)}`);
388705
+ }
388706
+ return [...new Set(result)];
388707
+ }
388708
+ function getAskUserQuestionCorrection(error40) {
388709
+ if (!error40.issues.some((issue2) => issue2.path[0] === "questions"))
388710
+ return null;
388711
+ const inferredCount = error40.issues.reduce((count3, issue2) => {
388712
+ const index2 = issue2.path[0] === "questions" ? issue2.path[1] : undefined;
388713
+ return typeof index2 === "number" ? Math.max(count3, index2 + 1) : count3;
388714
+ }, 0);
388715
+ const countNotice = inferredCount > 4 ? ` This call contains at least ${inferredCount} incomplete question entries.` : "";
388716
+ return "AskUserQuestion requires 1-4 complete question objects. Each object must " + "contain `question`, `header`, and an `options` array with 2-8 " + "objects containing `label`; include `description` only when it adds a " + "useful consequence or trade-off." + countNotice + " Do not invent missing choices or truncate entries. Retry with at most " + "four complete questions, ask remaining decisions in later rounds, and " + "do not repeat the unchanged call.";
388717
+ }
388718
+ function getWriteCorrection(error40) {
388719
+ const missingRequiredField = error40.issues.some((issue2) => issue2.code === "invalid_type" && issue2.message.includes("received undefined") && (issue2.path[0] === "file_path" || issue2.path[0] === "content"));
388720
+ if (!missingRequiredField)
388721
+ return null;
388722
+ return "No file was written. Write requires both `file_path` and `content` in " + "the same structured tool call. Assistant prose outside the call is not " + "file content and will not be copied into it. Retry only after supplying " + "the complete intended file text in `content`; do not repeat the " + "unchanged call or claim the file was created until Write returns success.";
388723
+ }
388423
388724
  function formatZodValidationError(toolName, error40) {
388424
- const missingParams = error40.issues.filter((err2) => err2.code === "invalid_type" && err2.message.includes("received undefined")).map((err2) => formatValidationPath(err2.path));
388425
- const unexpectedParams = error40.issues.filter((err2) => err2.code === "unrecognized_keys").flatMap((err2) => err2.keys);
388725
+ const missingParamErrors = formatMissingParameterErrors(error40);
388726
+ const sizeConstraintErrors = formatSizeConstraintErrors(error40);
388727
+ const unexpectedParams = [
388728
+ ...new Set(error40.issues.filter((err2) => err2.code === "unrecognized_keys").flatMap((err2) => err2.keys))
388729
+ ];
388426
388730
  const typeMismatchParams = error40.issues.filter((err2) => err2.code === "invalid_type" && !err2.message.includes("received undefined")).map((err2) => {
388427
388731
  const typeErr = err2;
388428
388732
  const receivedMatch = err2.message.match(/received (\w+)/);
@@ -388435,10 +388739,8 @@ function formatZodValidationError(toolName, error40) {
388435
388739
  });
388436
388740
  let errorContent = error40.message;
388437
388741
  const errorParts = [];
388438
- if (missingParams.length > 0) {
388439
- const missingParamErrors = missingParams.map((param) => `The required parameter \`${param}\` is missing`);
388440
- errorParts.push(...missingParamErrors);
388441
- }
388742
+ errorParts.push(...sizeConstraintErrors);
388743
+ errorParts.push(...missingParamErrors);
388442
388744
  if (unexpectedParams.length > 0) {
388443
388745
  const unexpectedParamErrors = unexpectedParams.map((param) => `An unexpected parameter \`${param}\` was provided`);
388444
388746
  errorParts.push(...unexpectedParamErrors);
@@ -388451,6 +388753,19 @@ function formatZodValidationError(toolName, error40) {
388451
388753
  errorContent = `${toolName} failed due to the following ${errorParts.length > 1 ? "issues" : "issue"}:
388452
388754
  ${errorParts.join(`
388453
388755
  `)}`;
388756
+ }
388757
+ if (toolName === "AskUserQuestion") {
388758
+ const correction = getAskUserQuestionCorrection(error40);
388759
+ if (correction)
388760
+ errorContent += `
388761
+
388762
+ ${correction}`;
388763
+ } else if (toolName === "Write") {
388764
+ const correction = getWriteCorrection(error40);
388765
+ if (correction)
388766
+ errorContent += `
388767
+
388768
+ ${correction}`;
388454
388769
  }
388455
388770
  return errorContent;
388456
388771
  }
@@ -388460,9 +388775,65 @@ var init_toolErrors = __esm(() => {
388460
388775
  });
388461
388776
 
388462
388777
  // src/services/tools/taskListGate.ts
388778
+ import { dirname as dirname45 } from "path";
388779
+ function isShellOperator(token, operator) {
388780
+ return typeof token === "object" && token !== null && "op" in token && token.op === operator;
388781
+ }
388782
+ function isPlanDirectoryBootstrapForGate(input) {
388783
+ if (typeof input.toolInput !== "object" || input.toolInput === null) {
388784
+ return false;
388785
+ }
388786
+ const candidate = input.toolInput;
388787
+ if (typeof candidate.command !== "string" || candidate.run_in_background === true || candidate.dangerouslyDisableSandbox === true || candidate._simulatedSedEdit !== undefined) {
388788
+ return false;
388789
+ }
388790
+ const command = candidate.command;
388791
+ if (command.includes("$") || command.includes("`") || command.includes("\\") || command.includes(`
388792
+ `) || command.includes("\r") || command.includes("\x00") || hasUnbalancedQuotes(command)) {
388793
+ return false;
388794
+ }
388795
+ const parsed = tryParseShellCommand(command);
388796
+ if (!parsed.success)
388797
+ return false;
388798
+ const tokens = parsed.tokens;
388799
+ let expectedPlanDirectory;
388800
+ try {
388801
+ expectedPlanDirectory = dirname45(expandPath(input.expectedPlanFile));
388802
+ } catch {
388803
+ return false;
388804
+ }
388805
+ const isPlanDirectory = (token) => {
388806
+ if (typeof token !== "string" || token.trim() === "")
388807
+ return false;
388808
+ try {
388809
+ return expandPath(token) === expectedPlanDirectory;
388810
+ } catch {
388811
+ return false;
388812
+ }
388813
+ };
388814
+ const isMkdir = tokens.length === 3 && tokens[0] === "mkdir" && tokens[1] === "-p" && isPlanDirectory(tokens[2]);
388815
+ if (isMkdir)
388816
+ return true;
388817
+ const hasSilentStderr = tokens[3] === "2" && isShellOperator(tokens[4], ">") && tokens[5] === "/dev/null";
388818
+ const guardOperatorIndex = hasSilentStderr ? 6 : 3;
388819
+ const mkdirIndex = guardOperatorIndex + 1;
388820
+ const hasGuardedMkdir = tokens[0] === "ls" && tokens[1] === "-la" && isPlanDirectory(tokens[2]) && isShellOperator(tokens[guardOperatorIndex], "||") && tokens[mkdirIndex] === "mkdir" && tokens[mkdirIndex + 1] === "-p" && isPlanDirectory(tokens[mkdirIndex + 2]);
388821
+ if (!hasGuardedMkdir)
388822
+ return false;
388823
+ const afterMkdir = mkdirIndex + 3;
388824
+ if (tokens.length === afterMkdir)
388825
+ return true;
388826
+ return tokens.length === afterMkdir + 4 && isShellOperator(tokens[afterMkdir], "&&") && tokens[afterMkdir + 1] === "ls" && tokens[afterMkdir + 2] === "-la" && isPlanDirectory(tokens[afterMkdir + 3]);
388827
+ }
388463
388828
  function isPlanArtifactMutationForGate(input) {
388464
388829
  if (!input.isPlanMode)
388465
388830
  return false;
388831
+ if (input.toolName === "Bash") {
388832
+ return isPlanDirectoryBootstrapForGate({
388833
+ toolInput: input.toolInput,
388834
+ expectedPlanFile: input.expectedPlanFile
388835
+ });
388836
+ }
388466
388837
  if (!PLAN_ARTIFACT_MUTATING_TOOLS.has(input.toolName))
388467
388838
  return false;
388468
388839
  if (typeof input.toolInput !== "object" || input.toolInput === null || !("file_path" in input.toolInput)) {
@@ -388477,6 +388848,36 @@ function isPlanArtifactMutationForGate(input) {
388477
388848
  return false;
388478
388849
  }
388479
388850
  }
388851
+ function isLocalPreviewOpenForTaskGate(input) {
388852
+ if (input.toolName !== "Bash" || typeof input.toolInput !== "object" || input.toolInput === null) {
388853
+ return false;
388854
+ }
388855
+ const candidate = input.toolInput;
388856
+ if (typeof candidate.command !== "string" || candidate.command.trim() === "" || candidate.run_in_background === true || candidate.dangerouslyDisableSandbox === true || candidate._simulatedSedEdit !== undefined) {
388857
+ return false;
388858
+ }
388859
+ const command = candidate.command;
388860
+ if (command.includes("$") || command.includes("`") || command.includes("\\") || command.includes(`
388861
+ `) || command.includes("\r") || command.includes("\x00") || hasUnbalancedQuotes(command)) {
388862
+ return false;
388863
+ }
388864
+ const parsed = tryParseShellCommand(command);
388865
+ if (!parsed.success || parsed.tokens.length !== 2 || parsed.tokens.some((token) => typeof token !== "string") || parsed.tokens[0] !== "open") {
388866
+ return false;
388867
+ }
388868
+ try {
388869
+ const url3 = new URL(parsed.tokens[1]);
388870
+ return (url3.protocol === "http:" || url3.protocol === "https:") && LOOPBACK_PREVIEW_HOSTS.has(url3.hostname) && url3.username === "" && url3.password === "";
388871
+ } catch {
388872
+ return false;
388873
+ }
388874
+ }
388875
+ function isMutationRequiringTaskList(input) {
388876
+ return input.isMutating && !isLocalPreviewOpenForTaskGate({
388877
+ toolName: input.toolName,
388878
+ toolInput: input.toolInput
388879
+ });
388880
+ }
388480
388881
  function getTaskListGateConfig() {
388481
388882
  const configured = getInitialSettings()?.tasks?.requireBeforeChanges;
388482
388883
  if (!configured)
@@ -388521,23 +388922,28 @@ function checkTaskListGate(input) {
388521
388922
  }
388522
388923
  if (input.isSubagent || ALWAYS_REQUIRE_PLAN_TOOLS.has(input.toolName)) {
388523
388924
  const taskTool2 = input.taskPlanningToolName ?? "TaskCreate";
388925
+ const terminalContext = input.totalTaskCount !== null && input.totalTaskCount !== undefined && input.totalTaskCount > 0 ? " The existing task list contains only terminal tasks." : "";
388524
388926
  return {
388525
388927
  allowed: false,
388526
- reason: `No actionable parent task exists for ${input.toolName}. Call ` + `${taskTool2} before delegating or changing state, then retry this call. ` + `${TASK_DECOMPOSITION_RECOVERY} ` + `Disable with tasks.requireBeforeChanges.enabled=false in settings.`
388928
+ reason: `No actionable parent task exists for ${input.toolName}.` + `${terminalContext} Call ${taskTool2} before delegating or changing ` + `state, then retry this call. ` + `${TASK_DECOMPOSITION_RECOVERY} ` + `Disable with tasks.requireBeforeChanges.enabled=false in settings.`
388527
388929
  };
388528
388930
  }
388529
388931
  if (input.readsSoFar < config2.freeReads)
388530
388932
  return { allowed: true };
388531
388933
  const taskTool = input.taskPlanningToolName ?? "TaskCreate";
388934
+ const hasTerminalTaskList = input.totalTaskCount !== null && input.totalTaskCount !== undefined && input.totalTaskCount > 0;
388935
+ const taskState = hasTerminalTaskList ? "The task list exists, but every tracked task is terminal, so no actionable task remains" : "No actionable task exists";
388936
+ const recovery = taskTool === "TodoWrite" ? "Call TodoWrite first to add a cohesive remaining todo or move the relevant todo back to pending/in_progress" : taskTool === "TaskCreate" ? "Call TaskCreate first to add a cohesive remaining task, or call TaskUpdate to move the relevant task back to pending/in_progress" : `Use ${taskTool} first to add or reopen a cohesive pending/in_progress task`;
388532
388937
  return {
388533
388938
  allowed: false,
388534
- reason: `No task list exists, and ${input.toolName} changes the workspace. ` + `Call ${taskTool} first, then retry this call. ` + `${TASK_DECOMPOSITION_RECOVERY} Reads are unrestricted, so investigate ` + `as much as you need before writing the list. ` + `Disable with tasks.requireBeforeChanges.enabled=false in settings.`
388939
+ reason: `${taskState}, and ${input.toolName} changes workspace state. ` + `${recovery}, then retry this call. Keep preview, launch, and ` + `verification work actionable until its observable check has actually ` + `run; do not mark that task complete before the check. ` + `${TASK_DECOMPOSITION_RECOVERY} Reads are unrestricted, so investigate ` + `as much as you need before writing the list. ` + `Disable with tasks.requireBeforeChanges.enabled=false in settings.`
388535
388940
  };
388536
388941
  }
388537
- var TASK_LIST_GATE_DEFAULTS, KNOWN_MUTATING_TOOLS, GATE_EXEMPT_TOOLS, ALWAYS_REQUIRE_PLAN_TOOLS, TASK_DECOMPOSITION_RECOVERY, PLAN_ARTIFACT_MUTATING_TOOLS;
388942
+ var TASK_LIST_GATE_DEFAULTS, KNOWN_MUTATING_TOOLS, GATE_EXEMPT_TOOLS, ALWAYS_REQUIRE_PLAN_TOOLS, TASK_DECOMPOSITION_RECOVERY, PLAN_ARTIFACT_MUTATING_TOOLS, LOOPBACK_PREVIEW_HOSTS;
388538
388943
  var init_taskListGate = __esm(() => {
388539
388944
  init_settings2();
388540
388945
  init_path();
388946
+ init_shellQuote();
388541
388947
  TASK_LIST_GATE_DEFAULTS = {
388542
388948
  enabled: true,
388543
388949
  freeReads: 3
@@ -388560,7 +388966,8 @@ var init_taskListGate = __esm(() => {
388560
388966
  "TaskUpdate",
388561
388967
  "TaskList",
388562
388968
  "TaskGet",
388563
- "TodoWrite"
388969
+ "TodoWrite",
388970
+ "ExitPlanMode"
388564
388971
  ]);
388565
388972
  ALWAYS_REQUIRE_PLAN_TOOLS = new Set([
388566
388973
  "Agent",
@@ -388572,6 +388979,11 @@ var init_taskListGate = __esm(() => {
388572
388979
  "Edit",
388573
388980
  "MultiEdit"
388574
388981
  ]);
388982
+ LOOPBACK_PREVIEW_HOSTS = new Set([
388983
+ "localhost",
388984
+ "127.0.0.1",
388985
+ "[::1]"
388986
+ ]);
388575
388987
  });
388576
388988
 
388577
388989
  // src/services/tools/repeatedFailureGuard.ts
@@ -388965,7 +389377,7 @@ var init_rootcause = __esm(() => {
388965
389377
 
388966
389378
  // src/stability/ledger.ts
388967
389379
  import { appendFileSync as appendFileSync4, existsSync as existsSync29, mkdirSync as mkdirSync19, readFileSync as readFileSync31 } from "fs";
388968
- import { dirname as dirname45, join as join109 } from "path";
389380
+ import { dirname as dirname46, join as join109 } from "path";
388969
389381
  function ledgerPath(cwd2) {
388970
389382
  return join109(cwd2, ".ur", "actions.jsonl");
388971
389383
  }
@@ -388993,7 +389405,7 @@ function filesFromArgs(args) {
388993
389405
  function recordAction(cwd2, record3) {
388994
389406
  try {
388995
389407
  const file2 = ledgerPath(cwd2);
388996
- mkdirSync19(dirname45(file2), { recursive: true });
389408
+ mkdirSync19(dirname46(file2), { recursive: true });
388997
389409
  appendFileSync4(file2, JSON.stringify(record3) + `
388998
389410
  `);
388999
389411
  } catch {}
@@ -389623,16 +390035,24 @@ async function countTasksForGate(toolUseContext) {
389623
390035
  const { getTaskListId: getTaskListId2, inspectTaskListForGate: inspectTaskListForGate2, isTodoV2Enabled: isTodoV2Enabled2 } = await Promise.resolve().then(() => (init_tasks(), exports_tasks));
389624
390036
  if (!isTodoV2Enabled2()) {
389625
390037
  const todoKey = toolUseContext.agentId ?? getSessionId();
389626
- return countActionableTodosForGate(toolUseContext.getAppState().todos?.[todoKey]);
390038
+ const todos = toolUseContext.getAppState().todos?.[todoKey] ?? [];
390039
+ return {
390040
+ actionableCount: countActionableTodosForGate(todos),
390041
+ totalCount: todos.length
390042
+ };
389627
390043
  }
389628
390044
  const inspection = await inspectTaskListForGate2(getTaskListId2());
389629
- return countActionableTasksForGate(inspection.tasks);
390045
+ const userTasks = inspection.tasks.filter((task) => !task.metadata?._internal);
390046
+ return {
390047
+ actionableCount: countActionableTasksForGate(userTasks),
390048
+ totalCount: userTasks.length
390049
+ };
389630
390050
  } catch {
389631
390051
  return null;
389632
390052
  }
389633
390053
  }
389634
390054
  function isCurrentPlanArtifactMutation(toolName, input, toolUseContext) {
389635
- if (toolName !== FILE_WRITE_TOOL_NAME && toolName !== FILE_EDIT_TOOL_NAME && toolName !== "MultiEdit") {
390055
+ if (toolName !== FILE_WRITE_TOOL_NAME && toolName !== FILE_EDIT_TOOL_NAME && toolName !== "MultiEdit" && toolName !== BASH_TOOL_NAME) {
389636
390056
  return false;
389637
390057
  }
389638
390058
  try {
@@ -390144,6 +390564,11 @@ async function checkPermissionsAndCallTool(tool, toolUseID, input, toolUseContex
390144
390564
  isMutating = true;
390145
390565
  }
390146
390566
  const isPlanArtifactMutation = isCurrentPlanArtifactMutation(tool.name, parsedInput.data, toolUseContext);
390567
+ const isTaskListGatedMutation = isMutationRequiringTaskList({
390568
+ toolName: tool.name,
390569
+ toolInput: parsedInput.data,
390570
+ isMutating
390571
+ });
390147
390572
  if (isMutating && isBuiltInReadOnlyPlanningSubagent(toolUseContext)) {
390148
390573
  recordCallFailure(callSig);
390149
390574
  return [
@@ -390161,12 +390586,14 @@ async function checkPermissionsAndCallTool(tool, toolUseID, input, toolUseContex
390161
390586
  }
390162
390587
  ];
390163
390588
  }
390589
+ const taskCounts = await countTasksForGate(toolUseContext);
390164
390590
  const gate = checkTaskListGate({
390165
390591
  toolName: tool.name,
390166
- taskCount: await countTasksForGate(toolUseContext),
390592
+ taskCount: taskCounts?.actionableCount ?? null,
390593
+ totalTaskCount: taskCounts?.totalCount ?? null,
390167
390594
  readsSoFar: countToolCallsBeforeCurrent(toolUseContext.messages, assistantMessage, toolUseID),
390168
390595
  isSubagent: Boolean(toolUseContext.agentId),
390169
- isMutating,
390596
+ isMutating: isTaskListGatedMutation,
390170
390597
  isPlanArtifactMutation,
390171
390598
  taskPlanningToolName: getTaskPlanningToolName(toolUseContext)
390172
390599
  });
@@ -390492,7 +390919,7 @@ async function checkPermissionsAndCallTool(tool, toolUseID, input, toolUseContex
390492
390919
  });
390493
390920
  return resultingMessages;
390494
390921
  }
390495
- if (callSig !== initiallyValidatedCallSig) {
390922
+ if (callSig !== initiallyValidatedCallSig || tool.requiresUserInteraction?.()) {
390496
390923
  const finalValidation = await tool.validateInput?.(finalParsedInput.data, {
390497
390924
  ...toolUseContext,
390498
390925
  validationPhase: "post-permission"
@@ -390524,6 +390951,11 @@ async function checkPermissionsAndCallTool(tool, toolUseID, input, toolUseContex
390524
390951
  finalIsMutating = true;
390525
390952
  }
390526
390953
  const finalIsPlanArtifactMutation = isCurrentPlanArtifactMutation(tool.name, finalParsedInput.data, toolUseContext);
390954
+ const finalIsTaskListGatedMutation = isMutationRequiringTaskList({
390955
+ toolName: tool.name,
390956
+ toolInput: finalParsedInput.data,
390957
+ isMutating: finalIsMutating
390958
+ });
390527
390959
  if (finalIsMutating && isBuiltInReadOnlyPlanningSubagent(toolUseContext)) {
390528
390960
  recordCallFailure(callSig);
390529
390961
  finishPreExecutionRejection();
@@ -390542,14 +390974,16 @@ async function checkPermissionsAndCallTool(tool, toolUseID, input, toolUseContex
390542
390974
  });
390543
390975
  return resultingMessages;
390544
390976
  }
390545
- const effectiveCallChanged = callSig !== initiallyValidatedCallSig || finalIsMutating !== isMutating || finalIsPlanArtifactMutation !== isPlanArtifactMutation;
390546
- if (finalIsMutating && !finalIsPlanArtifactMutation) {
390977
+ const effectiveCallChanged = callSig !== initiallyValidatedCallSig || finalIsMutating !== isMutating || finalIsTaskListGatedMutation !== isTaskListGatedMutation || finalIsPlanArtifactMutation !== isPlanArtifactMutation;
390978
+ if (finalIsTaskListGatedMutation && !finalIsPlanArtifactMutation) {
390979
+ const finalTaskCounts = await countTasksForGate(toolUseContext);
390547
390980
  const finalGate = checkTaskListGate({
390548
390981
  toolName: tool.name,
390549
- taskCount: await countTasksForGate(toolUseContext),
390982
+ taskCount: finalTaskCounts?.actionableCount ?? null,
390983
+ totalTaskCount: finalTaskCounts?.totalCount ?? null,
390550
390984
  readsSoFar: countToolCallsBeforeCurrent(toolUseContext.messages, assistantMessage, toolUseID),
390551
390985
  isSubagent: Boolean(toolUseContext.agentId),
390552
- isMutating: finalIsMutating,
390986
+ isMutating: finalIsTaskListGatedMutation,
390553
390987
  isPlanArtifactMutation: finalIsPlanArtifactMutation,
390554
390988
  taskPlanningToolName: getTaskPlanningToolName(toolUseContext)
390555
390989
  });
@@ -391354,6 +391788,292 @@ var init_StreamingToolExecutor = __esm(() => {
391354
391788
  init_toolExecution();
391355
391789
  });
391356
391790
 
391791
+ // src/utils/explicitChoiceRecovery.ts
391792
+ function objectValue4(value) {
391793
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
391794
+ }
391795
+ function hasOnlyKeys(value, required2, optional3 = []) {
391796
+ const allowed = new Set([...required2, ...optional3]);
391797
+ const keys2 = Object.keys(value);
391798
+ return required2.every((key) => Object.prototype.hasOwnProperty.call(value, key)) && keys2.every((key) => allowed.has(key));
391799
+ }
391800
+ function hasCanonicalAskShape(value) {
391801
+ const input = objectValue4(value);
391802
+ if (!input || !hasOnlyKeys(input, ["questions"], ["metadata"]) || !Array.isArray(input.questions) || input.questions.length < 1 || input.questions.length > MAX_QUESTIONS2) {
391803
+ return false;
391804
+ }
391805
+ if (input.metadata !== undefined && !objectValue4(input.metadata)) {
391806
+ return false;
391807
+ }
391808
+ return input.questions.every((questionValue) => {
391809
+ const question = objectValue4(questionValue);
391810
+ if (!question || !hasOnlyKeys(question, ["question", "header", "options"], ["multiSelect"]) || typeof question.question !== "string" || typeof question.header !== "string" || !Array.isArray(question.options) || question.options.length < 2 || question.options.length > MAX_OPTIONS2 || question.multiSelect !== undefined && typeof question.multiSelect !== "boolean") {
391811
+ return false;
391812
+ }
391813
+ return question.options.every((optionValue) => {
391814
+ const option = objectValue4(optionValue);
391815
+ return Boolean(option && hasOnlyKeys(option, ["label"], ["description", "preview"]) && typeof option.label === "string" && (option.description === undefined || typeof option.description === "string") && (option.preview === undefined || typeof option.preview === "string"));
391816
+ });
391817
+ });
391818
+ }
391819
+ function findJsonObjectEnd2(text, start) {
391820
+ let depth = 0;
391821
+ let inString = false;
391822
+ let escaped = false;
391823
+ for (let index2 = start;index2 < text.length; index2++) {
391824
+ const character = text[index2];
391825
+ if (inString) {
391826
+ if (escaped) {
391827
+ escaped = false;
391828
+ } else if (character === "\\") {
391829
+ escaped = true;
391830
+ } else if (character === '"') {
391831
+ inString = false;
391832
+ }
391833
+ continue;
391834
+ }
391835
+ if (character === '"') {
391836
+ inString = true;
391837
+ } else if (character === "{") {
391838
+ depth++;
391839
+ } else if (character === "}") {
391840
+ depth--;
391841
+ if (depth === 0)
391842
+ return index2 + 1;
391843
+ if (depth < 0)
391844
+ return null;
391845
+ }
391846
+ }
391847
+ return null;
391848
+ }
391849
+ function hasExplicitAskToolIntent(prefix) {
391850
+ const nearby = prefix.slice(-1000);
391851
+ if (/\b(?:for example|example|sample|illustration|schema)\b/i.test(nearby.slice(-240))) {
391852
+ return false;
391853
+ }
391854
+ return /\b(?:use|using|call|calling|invoke|invoking|emit|emitting)\b[\s\S]{0,100}\bAskUserQuestion\b/i.test(nearby) || /\bAskUserQuestion\b[\s\S]{0,100}\b(?:tool|call|invoke)\b/i.test(nearby);
391855
+ }
391856
+ function parseFinalReasoningAskJson(reasoning) {
391857
+ if (reasoning.length === 0 || reasoning.length > MAX_REASONING_CHARS) {
391858
+ return null;
391859
+ }
391860
+ const trimmed = reasoning.trimEnd();
391861
+ if (!trimmed.endsWith("}"))
391862
+ return null;
391863
+ const candidates2 = [];
391864
+ for (let start = trimmed.indexOf("{");start !== -1; start = trimmed.indexOf("{", start + 1)) {
391865
+ const end = findJsonObjectEnd2(trimmed, start);
391866
+ if (end !== trimmed.length)
391867
+ continue;
391868
+ try {
391869
+ const parsed = JSON.parse(trimmed.slice(start));
391870
+ if (hasCanonicalAskShape(parsed)) {
391871
+ candidates2.push({ start, input: parsed });
391872
+ }
391873
+ } catch {}
391874
+ }
391875
+ if (candidates2.length !== 1)
391876
+ return null;
391877
+ const candidate = candidates2[0];
391878
+ const prefix = trimmed.slice(0, candidate.start);
391879
+ if (prefix.includes("```") || !hasExplicitAskToolIntent(prefix))
391880
+ return null;
391881
+ return candidate.input;
391882
+ }
391883
+ function headerFromQuestion3(question) {
391884
+ const stopWords = new Set([
391885
+ "a",
391886
+ "about",
391887
+ "also",
391888
+ "an",
391889
+ "are",
391890
+ "be",
391891
+ "do",
391892
+ "does",
391893
+ "for",
391894
+ "is",
391895
+ "or",
391896
+ "should",
391897
+ "support",
391898
+ "that",
391899
+ "the",
391900
+ "this",
391901
+ "to",
391902
+ "want",
391903
+ "we",
391904
+ "what",
391905
+ "which",
391906
+ "with",
391907
+ "without",
391908
+ "you"
391909
+ ]);
391910
+ const word = question.replace(/[^A-Za-z0-9]+/g, " ").split(/\s+/).find((part) => part && !stopWords.has(part.toLowerCase()));
391911
+ const header = word ?? "Choice";
391912
+ return (header.slice(0, 1).toLocaleUpperCase() + header.slice(1)).slice(0, 12);
391913
+ }
391914
+ function parseExplicitChoicePrompt(text) {
391915
+ if (!text || text.length > MAX_MENU_CHARS || /```|[{}]/.test(text)) {
391916
+ return null;
391917
+ }
391918
+ const lines = text.replace(/\r\n?/g, `
391919
+ `).split(`
391920
+ `).map((line) => line.trim()).filter(Boolean);
391921
+ const questionIndexes = lines.flatMap((line, index2) => /^\*\*[^*\n]+\?\*\*$/.test(line) ? [index2] : []);
391922
+ if (questionIndexes.length !== 1)
391923
+ return null;
391924
+ const questionIndex = questionIndexes[0];
391925
+ const preamble = lines.slice(0, questionIndex);
391926
+ if (preamble.length > 2 || preamble.some((line) => line.length > 500 || line.includes("?") || /^[-*+#>]/.test(line))) {
391927
+ return null;
391928
+ }
391929
+ const questionMatch = lines[questionIndex].match(/^\*\*([^*\n]+\?)\*\*$/);
391930
+ const question = questionMatch?.[1];
391931
+ if (!question || question.length > MAX_QUESTION_CHARS2)
391932
+ return null;
391933
+ const options2 = [];
391934
+ let lineIndex = questionIndex + 1;
391935
+ while (lineIndex < lines.length) {
391936
+ const match = lines[lineIndex].match(/^-\s+\*\*([^*\n]+)\*\*\s+[\u2013\u2014]\s+(.+)$/);
391937
+ if (!match)
391938
+ break;
391939
+ const label = match[1];
391940
+ const description = match[2];
391941
+ const normalizedLabel = label.toLocaleLowerCase();
391942
+ if (label.length > MAX_LABEL_CHARS2 || description.length > MAX_DESCRIPTION_CHARS2 || normalizedLabel === "other" || normalizedLabel === "__other__") {
391943
+ return null;
391944
+ }
391945
+ options2.push({ label, description });
391946
+ lineIndex++;
391947
+ }
391948
+ if (options2.length < 2 || options2.length > MAX_OPTIONS2)
391949
+ return null;
391950
+ if (new Set(options2.map((option) => option.label.toLocaleLowerCase())).size !== options2.length) {
391951
+ return null;
391952
+ }
391953
+ const trailing = lines.slice(lineIndex);
391954
+ if (trailing.length !== 1 || trailing[0].includes("?") || !/^(?:please\s+)?(?:select|choose|pick)\b.{0,120}\b(?:option|choice)\b/i.test(trailing[0])) {
391955
+ return null;
391956
+ }
391957
+ return {
391958
+ input: {
391959
+ questions: [
391960
+ {
391961
+ question,
391962
+ header: headerFromQuestion3(question),
391963
+ options: options2
391964
+ }
391965
+ ]
391966
+ },
391967
+ source: "markdown_menu",
391968
+ remainingText: preamble.join(`
391969
+ `)
391970
+ };
391971
+ }
391972
+ function collectExplicitChoiceCandidates({
391973
+ thinkingBlocks,
391974
+ textBlocks
391975
+ }) {
391976
+ const candidates2 = [];
391977
+ const reasoningCandidates = thinkingBlocks.map(parseFinalReasoningAskJson).filter((input) => input !== null);
391978
+ if (reasoningCandidates.length === 1) {
391979
+ candidates2.push({
391980
+ input: reasoningCandidates[0],
391981
+ source: "thinking_json",
391982
+ remainingText: ""
391983
+ });
391984
+ }
391985
+ const menuCandidates = textBlocks.map(parseExplicitChoicePrompt).filter((candidate) => candidate !== null);
391986
+ if (menuCandidates.length === 1) {
391987
+ candidates2.push(menuCandidates[0]);
391988
+ }
391989
+ return candidates2;
391990
+ }
391991
+ var MAX_REASONING_CHARS, MAX_MENU_CHARS, MAX_QUESTION_CHARS2 = 500, MAX_LABEL_CHARS2 = 80, MAX_DESCRIPTION_CHARS2 = 500, MAX_OPTIONS2 = 8, MAX_QUESTIONS2 = 4;
391992
+ var init_explicitChoiceRecovery = __esm(() => {
391993
+ MAX_REASONING_CHARS = 64 * 1024;
391994
+ MAX_MENU_CHARS = 4 * 1024;
391995
+ });
391996
+
391997
+ // src/services/tools/explicitChoiceRecovery.ts
391998
+ import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
391999
+ function recoverExplicitChoiceToolUse({
392000
+ assistantMessages,
392001
+ tools,
392002
+ agentId,
392003
+ isNonInteractiveSession,
392004
+ uuid: uuid3
392005
+ }) {
392006
+ if (assistantMessages.length === 0 || agentId !== undefined || isNonInteractiveSession || assistantMessages.some((message) => {
392007
+ const content = message.message?.content;
392008
+ return message.isApiErrorMessage || Array.isArray(content) && content.some((block2) => block2.type === "tool_use");
392009
+ })) {
392010
+ return null;
392011
+ }
392012
+ const sourceMessage = assistantMessages.at(-1);
392013
+ if (!sourceMessage?.message || sourceMessage.message.stop_reason !== "end_turn") {
392014
+ return null;
392015
+ }
392016
+ const askTool = findToolByName(tools, ASK_USER_QUESTION_TOOL_NAME);
392017
+ if (!askTool)
392018
+ return null;
392019
+ try {
392020
+ if (!askTool.isEnabled())
392021
+ return null;
392022
+ } catch {
392023
+ return null;
392024
+ }
392025
+ const thinkingBlocks = [];
392026
+ const textBlocks = [];
392027
+ for (const assistantMessage of assistantMessages) {
392028
+ const content = assistantMessage.message?.content;
392029
+ if (!Array.isArray(content))
392030
+ continue;
392031
+ for (const block2 of content) {
392032
+ if (block2.type === "thinking" && typeof block2.thinking === "string") {
392033
+ thinkingBlocks.push(block2.thinking);
392034
+ } else if (block2.type === "text" && typeof block2.text === "string") {
392035
+ textBlocks.push(block2.text);
392036
+ }
392037
+ }
392038
+ }
392039
+ for (const candidate of collectExplicitChoiceCandidates({
392040
+ thinkingBlocks,
392041
+ textBlocks
392042
+ })) {
392043
+ const parsed = askTool.inputSchema.safeParse(candidate.input);
392044
+ if (!parsed.success || !isDeepStrictEqual3(parsed.data, candidate.input)) {
392045
+ continue;
392046
+ }
392047
+ const idSuffix = uuid3().replace(/[^A-Za-z0-9]/g, "");
392048
+ const toolUse = {
392049
+ type: "tool_use",
392050
+ id: `toolu_recovered_${idSuffix}`,
392051
+ name: ASK_USER_QUESTION_TOOL_NAME,
392052
+ input: parsed.data
392053
+ };
392054
+ const assistantMessage = {
392055
+ ...sourceMessage,
392056
+ uuid: uuid3(),
392057
+ message: {
392058
+ ...sourceMessage.message,
392059
+ content: [toolUse],
392060
+ stop_reason: "tool_use"
392061
+ }
392062
+ };
392063
+ return {
392064
+ assistantMessage,
392065
+ source: candidate.source,
392066
+ toolUse
392067
+ };
392068
+ }
392069
+ return null;
392070
+ }
392071
+ var init_explicitChoiceRecovery2 = __esm(() => {
392072
+ init_Tool();
392073
+ init_prompt9();
392074
+ init_explicitChoiceRecovery();
392075
+ });
392076
+
391357
392077
  // src/utils/queryProfiler.ts
391358
392078
  function startQueryProfile() {
391359
392079
  if (!ENABLED)
@@ -392453,7 +393173,7 @@ import {
392453
393173
  unlinkSync as unlinkSync8,
392454
393174
  writeFileSync as writeFileSync20
392455
393175
  } from "fs";
392456
- import { isAbsolute as isAbsolute30, dirname as dirname46, join as join111, relative as relative29, sep as sep25 } from "path";
393176
+ import { isAbsolute as isAbsolute30, dirname as dirname47, join as join111, relative as relative29, sep as sep25 } from "path";
392457
393177
  function readJsonl(file2) {
392458
393178
  if (!file2 || !existsSync30(file2))
392459
393179
  return [];
@@ -392481,7 +393201,7 @@ function append2(file2, rec) {
392481
393201
  });
392482
393202
  }
392483
393203
  function writeAtomic(file2, content) {
392484
- mkdirSync20(dirname46(file2), { recursive: true });
393204
+ mkdirSync20(dirname47(file2), { recursive: true });
392485
393205
  const temporary = `${file2}.${process.pid}.${Date.now()}.tmp`;
392486
393206
  try {
392487
393207
  writeFileSync20(temporary, content, { mode: 384 });
@@ -392527,7 +393247,7 @@ function projectStoreFile(cwd2, directory, name, create2) {
392527
393247
  }
392528
393248
  return create2 || existsSync30(target) ? target : undefined;
392529
393249
  }
392530
- function boundedText(text) {
393250
+ function boundedText2(text) {
392531
393251
  const normalized = text.trim();
392532
393252
  if (!normalized)
392533
393253
  throw new Error("note text cannot be empty");
@@ -392591,7 +393311,7 @@ function rememberInAutoMemory(memoryDir, text) {
392591
393311
  function remember(cwd2, text) {
392592
393312
  append2(memFile(cwd2, true), {
392593
393313
  ts: new Date().toISOString(),
392594
- text: boundedText(text),
393314
+ text: boundedText2(text),
392595
393315
  kind: "note"
392596
393316
  });
392597
393317
  }
@@ -392641,7 +393361,7 @@ function forgetInAutoMemory(memoryDir, texts) {
392641
393361
  function addResearch(cwd2, kind, text) {
392642
393362
  append2(researchFile(cwd2, kind, true), {
392643
393363
  ts: new Date().toISOString(),
392644
- text: boundedText(text),
393364
+ text: boundedText2(text),
392645
393365
  kind
392646
393366
  });
392647
393367
  }
@@ -393507,6 +394227,25 @@ async function* queryLoop(params, consumedCommandUuids, ownedRepeatedFailureQuer
393507
394227
  logAntError("Query error", error40);
393508
394228
  return { reason: "model_error", error: error40 };
393509
394229
  }
394230
+ if (!toolUseContext.abortController.signal.aborted) {
394231
+ const recoveredChoice = recoverExplicitChoiceToolUse({
394232
+ assistantMessages,
394233
+ tools: toolUseContext.options.tools,
394234
+ agentId: toolUseContext.agentId,
394235
+ isNonInteractiveSession: Boolean(toolUseContext.options.isNonInteractiveSession),
394236
+ uuid: deps.uuid
394237
+ });
394238
+ if (recoveredChoice) {
394239
+ assistantMessages.push(recoveredChoice.assistantMessage);
394240
+ toolUseBlocks.push(recoveredChoice.toolUse);
394241
+ needsFollowUp = true;
394242
+ logForDebugging(`Recovered explicit AskUserQuestion call from ${recoveredChoice.source}`);
394243
+ yield recoveredChoice.assistantMessage;
394244
+ if (streamingToolExecutor && !toolUseContext.abortController.signal.aborted) {
394245
+ streamingToolExecutor.addTool(recoveredChoice.toolUse, recoveredChoice.assistantMessage);
394246
+ }
394247
+ }
394248
+ }
393510
394249
  if (assistantMessages.length > 0) {
393511
394250
  executePostSamplingHooks([...messagesForQuery, ...assistantMessages], systemPrompt, userContext, systemContext, toolUseContext, querySource);
393512
394251
  }
@@ -394013,6 +394752,7 @@ var init_query = __esm(() => {
394013
394752
  init_dumpPrompts();
394014
394753
  init_verifier();
394015
394754
  init_StreamingToolExecutor();
394755
+ init_explicitChoiceRecovery2();
394016
394756
  init_queryProfiler();
394017
394757
  init_toolOrchestration();
394018
394758
  init_repeatedFailureGuard();
@@ -397438,21 +398178,6 @@ var init_analyzeContext = __esm(() => {
397438
398178
  init_tokens();
397439
398179
  });
397440
398180
 
397441
- // src/utils/zodToJsonSchema.ts
397442
- function zodToJsonSchema3(schema) {
397443
- const hit = cache3.get(schema);
397444
- if (hit)
397445
- return hit;
397446
- const result = toJSONSchema(schema);
397447
- cache3.set(schema, result);
397448
- return result;
397449
- }
397450
- var cache3;
397451
- var init_zodToJsonSchema2 = __esm(() => {
397452
- init_v4();
397453
- cache3 = new WeakMap;
397454
- });
397455
-
397456
398181
  // src/utils/toolSearch.ts
397457
398182
  var exports_toolSearch = {};
397458
398183
  __export(exports_toolSearch, {
@@ -397780,7 +398505,7 @@ var init_toolSearch = __esm(() => {
397780
398505
  // src/services/vcr.ts
397781
398506
  import { createHash as createHash34, randomUUID as randomUUID39 } from "crypto";
397782
398507
  import { mkdir as mkdir24, readFile as readFile33, writeFile as writeFile24 } from "fs/promises";
397783
- import { dirname as dirname47, join as join114 } from "path";
398508
+ import { dirname as dirname48, join as join114 } from "path";
397784
398509
  function shouldUseVCR() {
397785
398510
  if (false) {}
397786
398511
  if (process.env.USER_TYPE === "ant" && isEnvTruthy(process.env.FORCE_VCR)) {
@@ -397807,7 +398532,7 @@ async function withFixture(input, fixtureName, f) {
397807
398532
  throw new Error(`Fixture missing: ${filename}. Re-run tests with VCR_RECORD=1, then commit the result.`);
397808
398533
  }
397809
398534
  const result = await f();
397810
- await mkdir24(dirname47(filename), { recursive: true });
398535
+ await mkdir24(dirname48(filename), { recursive: true });
397811
398536
  await writeFile24(filename, jsonStringify(result, null, 2), {
397812
398537
  encoding: "utf8"
397813
398538
  });
@@ -397846,7 +398571,7 @@ ${jsonStringify(dehydratedInput, null, 2)}`);
397846
398571
  if (env2.isCI && !isEnvTruthy(process.env.VCR_RECORD)) {
397847
398572
  return results;
397848
398573
  }
397849
- await mkdir24(dirname47(filename), { recursive: true });
398574
+ await mkdir24(dirname48(filename), { recursive: true });
397850
398575
  await writeFile24(filename, jsonStringify({
397851
398576
  input: dehydratedInput,
397852
398577
  output: results.map((message, index2) => mapMessage(message, dehydrateValue, index2))
@@ -399991,7 +400716,7 @@ var init_findRelevantMemories = __esm(() => {
399991
400716
 
399992
400717
  // src/utils/attachments.ts
399993
400718
  import { readdir as readdir18, stat as stat32 } from "fs/promises";
399994
- import { dirname as dirname48, parse as parse13, relative as relative30, resolve as resolve40 } from "path";
400719
+ import { dirname as dirname49, parse as parse13, relative as relative30, resolve as resolve40 } from "path";
399995
400720
  import { randomUUID as randomUUID41 } from "crypto";
399996
400721
  function isAttachment(value) {
399997
400722
  return typeof value === "object" && value !== null && "type" in value;
@@ -400384,21 +401109,21 @@ async function getSelectedLinesFromIDE(ideSelection, toolUseContext) {
400384
401109
  ];
400385
401110
  }
400386
401111
  function getDirectoriesToProcess(targetPath, originalCwd) {
400387
- const targetDir = dirname48(resolve40(targetPath));
401112
+ const targetDir = dirname49(resolve40(targetPath));
400388
401113
  const nestedDirs = [];
400389
401114
  let currentDir = targetDir;
400390
401115
  while (currentDir !== originalCwd && currentDir !== parse13(currentDir).root) {
400391
401116
  if (currentDir.startsWith(originalCwd)) {
400392
401117
  nestedDirs.push(currentDir);
400393
401118
  }
400394
- currentDir = dirname48(currentDir);
401119
+ currentDir = dirname49(currentDir);
400395
401120
  }
400396
401121
  nestedDirs.reverse();
400397
401122
  const cwdLevelDirs = [];
400398
401123
  currentDir = originalCwd;
400399
401124
  while (currentDir !== parse13(currentDir).root) {
400400
401125
  cwdLevelDirs.push(currentDir);
400401
- currentDir = dirname48(currentDir);
401126
+ currentDir = dirname49(currentDir);
400402
401127
  }
400403
401128
  cwdLevelDirs.reverse();
400404
401129
  return { nestedDirs, cwdLevelDirs };
@@ -401644,21 +402369,21 @@ var init_attachments2 = __esm(() => {
401644
402369
  });
401645
402370
 
401646
402371
  // src/utils/plugins/loadPluginCommands.ts
401647
- import { basename as basename32, dirname as dirname49, join as join117 } from "path";
402372
+ import { basename as basename32, dirname as dirname50, join as join117 } from "path";
401648
402373
  function isSkillFile2(filePath) {
401649
402374
  return /^skill\.md$/i.test(basename32(filePath));
401650
402375
  }
401651
402376
  function getCommandNameFromFile(filePath, baseDir, pluginName) {
401652
402377
  const isSkill = isSkillFile2(filePath);
401653
402378
  if (isSkill) {
401654
- const skillDirectory = dirname49(filePath);
401655
- const parentOfSkillDir = dirname49(skillDirectory);
402379
+ const skillDirectory = dirname50(filePath);
402380
+ const parentOfSkillDir = dirname50(skillDirectory);
401656
402381
  const commandBaseName = basename32(skillDirectory);
401657
402382
  const relativePath = parentOfSkillDir.startsWith(baseDir) ? parentOfSkillDir.slice(baseDir.length).replace(/^\//, "") : "";
401658
402383
  const namespace = relativePath ? relativePath.split("/").join(":") : "";
401659
402384
  return namespace ? `${pluginName}:${namespace}:${commandBaseName}` : `${pluginName}:${commandBaseName}`;
401660
402385
  } else {
401661
- const fileDirectory = dirname49(filePath);
402386
+ const fileDirectory = dirname50(filePath);
401662
402387
  const commandBaseName = basename32(filePath).replace(/\.md$/, "");
401663
402388
  const relativePath = fileDirectory.startsWith(baseDir) ? fileDirectory.slice(baseDir.length).replace(/^\//, "") : "";
401664
402389
  const namespace = relativePath ? relativePath.split("/").join(":") : "";
@@ -401685,7 +402410,7 @@ async function collectMarkdownFiles(dirPath, baseDir, loadedPaths) {
401685
402410
  function transformPluginSkillFiles(files) {
401686
402411
  const filesByDir = new Map;
401687
402412
  for (const file2 of files) {
401688
- const dir = dirname49(file2.filePath);
402413
+ const dir = dirname50(file2.filePath);
401689
402414
  const dirFiles = filesByDir.get(dir) ?? [];
401690
402415
  dirFiles.push(file2);
401691
402416
  filesByDir.set(dir, dirFiles);
@@ -401774,7 +402499,7 @@ function createPluginCommand(commandName, file2, sourceName, pluginManifest, plu
401774
402499
  return displayName || commandName;
401775
402500
  },
401776
402501
  async getPromptForCommand(args, context5) {
401777
- let finalContent = config2.isSkillMode ? `Base directory for this skill: ${dirname49(file2.filePath)}
402502
+ let finalContent = config2.isSkillMode ? `Base directory for this skill: ${dirname50(file2.filePath)}
401778
402503
 
401779
402504
  ${content}` : content;
401780
402505
  finalContent = substituteArguments(finalContent, args, true, argumentNames);
@@ -401786,7 +402511,7 @@ ${content}` : content;
401786
402511
  finalContent = substituteUserConfigInContent(finalContent, loadPluginOptions(sourceName), pluginManifest.userConfig);
401787
402512
  }
401788
402513
  if (config2.isSkillMode) {
401789
- const rawSkillDir = dirname49(file2.filePath);
402514
+ const rawSkillDir = dirname50(file2.filePath);
401790
402515
  const skillDir = process.platform === "win32" ? rawSkillDir.replace(/\\/g, "/") : rawSkillDir;
401791
402516
  finalContent = finalContent.replace(/\$\{UR_SKILL_DIR\}/g, skillDir);
401792
402517
  }
@@ -401846,7 +402571,7 @@ async function loadSkillsFromDirectory(skillsPath, pluginName, sourceName, plugi
401846
402571
  const skillName = `${pluginName}:${basename32(skillsPath)}`;
401847
402572
  const file2 = {
401848
402573
  filePath: directSkillPath,
401849
- baseDir: dirname49(directSkillPath),
402574
+ baseDir: dirname50(directSkillPath),
401850
402575
  frontmatter,
401851
402576
  content: markdownContent
401852
402577
  };
@@ -401895,7 +402620,7 @@ async function loadSkillsFromDirectory(skillsPath, pluginName, sourceName, plugi
401895
402620
  const skillName = `${pluginName}:${entry.name}`;
401896
402621
  const file2 = {
401897
402622
  filePath: skillFilePath,
401898
- baseDir: dirname49(skillFilePath),
402623
+ baseDir: dirname50(skillFilePath),
401899
402624
  frontmatter,
401900
402625
  content: markdownContent
401901
402626
  };
@@ -402008,7 +402733,7 @@ var init_loadPluginCommands = __esm(() => {
402008
402733
  } : frontmatter;
402009
402734
  const file2 = {
402010
402735
  filePath: commandPath,
402011
- baseDir: dirname49(commandPath),
402736
+ baseDir: dirname50(commandPath),
402012
402737
  frontmatter: finalFrontmatter,
402013
402738
  content: markdownContent
402014
402739
  };
@@ -402271,7 +402996,7 @@ import {
402271
402996
  writeFile as writeFile25
402272
402997
  } from "fs/promises";
402273
402998
  import { tmpdir as tmpdir9 } from "os";
402274
- import { basename as basename34, dirname as dirname51, join as join119 } from "path";
402999
+ import { basename as basename34, dirname as dirname52, join as join119 } from "path";
402275
403000
  function isPluginZipCacheEnabled() {
402276
403001
  return isEnvTruthy(process.env.UR_CODE_PLUGIN_USE_ZIP_CACHE);
402277
403002
  }
@@ -402334,7 +403059,7 @@ async function cleanupSessionPluginCache() {
402334
403059
  }
402335
403060
  }
402336
403061
  async function atomicWriteToZipCache(targetPath, data) {
402337
- const dir = dirname51(targetPath);
403062
+ const dir = dirname52(targetPath);
402338
403063
  await getFsImplementation().mkdir(dir);
402339
403064
  const tmpName = `.${basename34(targetPath)}.tmp.${randomBytes13(4).toString("hex")}`;
402340
403065
  const tmpPath = join119(dir, tmpName);
@@ -402431,7 +403156,7 @@ async function extractZipToDirectory(zipPath, targetDir) {
402431
403156
  continue;
402432
403157
  }
402433
403158
  const fullPath = join119(targetDir, relPath);
402434
- await getFsImplementation().mkdir(dirname51(fullPath));
403159
+ await getFsImplementation().mkdir(dirname52(fullPath));
402435
403160
  await writeFile25(fullPath, data);
402436
403161
  const mode = modes[relPath];
402437
403162
  if (mode && mode & 73) {
@@ -402927,7 +403652,7 @@ var init_marketplaceHelpers = __esm(() => {
402927
403652
 
402928
403653
  // src/utils/plugins/officialMarketplaceGcs.ts
402929
403654
  import { chmod as chmod9, mkdir as mkdir26, readFile as readFile36, rename as rename5, rm as rm7, writeFile as writeFile27 } from "fs/promises";
402930
- import { dirname as dirname52, join as join121, resolve as resolve41, sep as sep26 } from "path";
403655
+ import { dirname as dirname53, join as join121, resolve as resolve41, sep as sep26 } from "path";
402931
403656
  async function fetchOfficialMarketplaceFromGcs(installLocation, marketplacesCacheDir) {
402932
403657
  if (!GCS_BASE) {
402933
403658
  return null;
@@ -402977,7 +403702,7 @@ async function fetchOfficialMarketplaceFromGcs(installLocation, marketplacesCach
402977
403702
  if (!rel || rel.endsWith("/"))
402978
403703
  continue;
402979
403704
  const dest = join121(staging, rel);
402980
- await mkdir26(dirname52(dest), { recursive: true });
403705
+ await mkdir26(dirname53(dest), { recursive: true });
402981
403706
  await writeFile27(dest, data);
402982
403707
  const mode = modes[arcPath];
402983
403708
  if (mode && mode & 73) {
@@ -403056,7 +403781,7 @@ var init_officialMarketplaceGcs = __esm(() => {
403056
403781
 
403057
403782
  // src/utils/plugins/marketplaceManager.ts
403058
403783
  import { writeFile as writeFile28 } from "fs/promises";
403059
- import { basename as basename35, dirname as dirname53, isAbsolute as isAbsolute31, join as join122, resolve as resolve42, sep as sep27 } from "path";
403784
+ import { basename as basename35, dirname as dirname54, isAbsolute as isAbsolute31, join as join122, resolve as resolve42, sep as sep27 } from "path";
403060
403785
  function getKnownMarketplacesFile() {
403061
403786
  return join122(getPluginsDirectory(), "known_marketplaces.json");
403062
403787
  }
@@ -403736,7 +404461,7 @@ async function loadAndCacheMarketplace(source, onProgress) {
403736
404461
  case "file": {
403737
404462
  const absPath = resolve42(source.path);
403738
404463
  marketplacePath = absPath;
403739
- temporaryCachePath = dirname53(dirname53(absPath));
404464
+ temporaryCachePath = dirname54(dirname54(absPath));
403740
404465
  cleanupNeeded = false;
403741
404466
  break;
403742
404467
  }
@@ -403751,7 +404476,7 @@ async function loadAndCacheMarketplace(source, onProgress) {
403751
404476
  temporaryCachePath = join122(cacheDir, source.name);
403752
404477
  marketplacePath = join122(temporaryCachePath, ".ur-plugin", "marketplace.json");
403753
404478
  cleanupNeeded = false;
403754
- await fs4.mkdir(dirname53(marketplacePath));
404479
+ await fs4.mkdir(dirname54(marketplacePath));
403755
404480
  await writeFile28(marketplacePath, jsonStringify({
403756
404481
  name: source.name,
403757
404482
  owner: source.owner ?? { name: "settings" },
@@ -404246,7 +404971,7 @@ var init_marketplaceManager = __esm(() => {
404246
404971
  });
404247
404972
 
404248
404973
  // src/utils/plugins/installedPluginsManager.ts
404249
- import { dirname as dirname54, join as join123 } from "path";
404974
+ import { dirname as dirname55, join as join123 } from "path";
404250
404975
  function getInstalledPluginsFilePath() {
404251
404976
  return join123(getPluginsDirectory(), "installed_plugins.json");
404252
404977
  }
@@ -404812,7 +405537,7 @@ var init_pluginVersioning = __esm(() => {
404812
405537
  // src/utils/plugins/pluginInstallationHelpers.ts
404813
405538
  import { randomBytes as randomBytes14 } from "crypto";
404814
405539
  import { rename as rename6, rm as rm8 } from "fs/promises";
404815
- import { dirname as dirname55, join as join124, resolve as resolve43, sep as sep28 } from "path";
405540
+ import { dirname as dirname56, join as join124, resolve as resolve43, sep as sep28 } from "path";
404816
405541
  function getCurrentTimestamp() {
404817
405542
  return new Date().toISOString();
404818
405543
  }
@@ -404836,14 +405561,14 @@ async function cacheAndRegisterPlugin(pluginId, entry, scope = "user", projectPa
404836
405561
  const versionedPath = getVersionedCachePath(pluginId, version2);
404837
405562
  let finalPath = cacheResult.path;
404838
405563
  if (cacheResult.path !== versionedPath) {
404839
- await getFsImplementation().mkdir(dirname55(versionedPath));
405564
+ await getFsImplementation().mkdir(dirname56(versionedPath));
404840
405565
  await rm8(versionedPath, { recursive: true, force: true });
404841
405566
  const normalizedCachePath = cacheResult.path.endsWith(sep28) ? cacheResult.path : cacheResult.path + sep28;
404842
405567
  const isSubdirectory = versionedPath.startsWith(normalizedCachePath);
404843
405568
  if (isSubdirectory) {
404844
- const tempPath = join124(dirname55(cacheResult.path), `.ur-plugin-temp-${Date.now()}-${randomBytes14(4).toString("hex")}`);
405569
+ const tempPath = join124(dirname56(cacheResult.path), `.ur-plugin-temp-${Date.now()}-${randomBytes14(4).toString("hex")}`);
404845
405570
  await rename6(cacheResult.path, tempPath);
404846
- await getFsImplementation().mkdir(dirname55(versionedPath));
405571
+ await getFsImplementation().mkdir(dirname56(versionedPath));
404847
405572
  await rename6(tempPath, versionedPath);
404848
405573
  } else {
404849
405574
  await rename6(cacheResult.path, versionedPath);
@@ -405072,7 +405797,7 @@ import {
405072
405797
  stat as stat35,
405073
405798
  symlink as symlink3
405074
405799
  } from "fs/promises";
405075
- import { basename as basename36, dirname as dirname56, join as join125, relative as relative31, resolve as resolve44, sep as sep29 } from "path";
405800
+ import { basename as basename36, dirname as dirname57, join as join125, relative as relative31, resolve as resolve44, sep as sep29 } from "path";
405076
405801
  function getPluginCachePath() {
405077
405802
  return join125(getPluginsDirectory(), "cache");
405078
405803
  }
@@ -405102,7 +405827,7 @@ async function probeSeedCache(pluginId, version2) {
405102
405827
  }
405103
405828
  async function probeSeedCacheAnyVersion(pluginId) {
405104
405829
  for (const seedDir of getPluginSeedDirs()) {
405105
- const pluginDir = dirname56(getVersionedCachePathIn(seedDir, pluginId, "_"));
405830
+ const pluginDir = dirname57(getVersionedCachePathIn(seedDir, pluginId, "_"));
405106
405831
  try {
405107
405832
  const versions2 = await readdir21(pluginDir);
405108
405833
  if (versions2.length !== 1)
@@ -405144,7 +405869,7 @@ async function copyDir(src, dest) {
405144
405869
  if (resolvedTarget.startsWith(srcPrefix) || resolvedTarget === resolvedSrc) {
405145
405870
  const targetRelativeToSrc = relative31(resolvedSrc, resolvedTarget);
405146
405871
  const destTargetPath = join125(dest, targetRelativeToSrc);
405147
- const relativeLinkPath = relative31(dirname56(destPath), destTargetPath);
405872
+ const relativeLinkPath = relative31(dirname57(destPath), destTargetPath);
405148
405873
  await symlink3(relativeLinkPath, destPath);
405149
405874
  } else {
405150
405875
  await symlink3(resolvedTarget, destPath);
@@ -405175,7 +405900,7 @@ async function copyPluginToVersionedCache(sourcePath, pluginId, version2, entry,
405175
405900
  logForDebugging(`Using seed cache for ${pluginId}@${version2} at ${seedPath}`);
405176
405901
  return seedPath;
405177
405902
  }
405178
- await getFsImplementation().mkdir(dirname56(cachePath));
405903
+ await getFsImplementation().mkdir(dirname57(cachePath));
405179
405904
  if (entry && typeof entry.source === "string" && marketplaceDir) {
405180
405905
  const sourceDir = validatePathWithinBase(marketplaceDir, entry.source);
405181
405906
  logForDebugging(`Copying source directory ${entry.source} for plugin ${pluginId}`);
@@ -413611,7 +414336,7 @@ __export(exports_terminalSetup, {
413611
414336
  import { randomBytes as randomBytes16 } from "crypto";
413612
414337
  import { copyFile as copyFile8, mkdir as mkdir27, readFile as readFile38, writeFile as writeFile29 } from "fs/promises";
413613
414338
  import { homedir as homedir28, platform as platform4 } from "os";
413614
- import { dirname as dirname57, join as join128 } from "path";
414339
+ import { dirname as dirname58, join as join128 } from "path";
413615
414340
  import { pathToFileURL as pathToFileURL7 } from "url";
413616
414341
  function isVSCodeRemoteSSH() {
413617
414342
  const askpassMain = process.env.VSCODE_GIT_ASKPASS_MAIN ?? "";
@@ -413933,7 +414658,7 @@ chars = "\\u001B\\r"`;
413933
414658
  return `${color("warning", theme)("Error backing up existing Alacritty config. Bailing out.")}${EOL5}${source_default.dim(`See ${formatPathLink(configPath)}`)}${EOL5}${source_default.dim(`Backup path: ${formatPathLink(backupPath)}`)}${EOL5}`;
413934
414659
  }
413935
414660
  } else {
413936
- await mkdir27(dirname57(configPath), {
414661
+ await mkdir27(dirname58(configPath), {
413937
414662
  recursive: true
413938
414663
  });
413939
414664
  }
@@ -416380,7 +417105,7 @@ var init_TextInput = __esm(() => {
416380
417105
  });
416381
417106
 
416382
417107
  // src/utils/suggestions/directoryCompletion.ts
416383
- import { basename as basename40, dirname as dirname58, join as join131, sep as sep30 } from "path";
417108
+ import { basename as basename40, dirname as dirname59, join as join131, sep as sep30 } from "path";
416384
417109
  function parsePartialPath(partialPath, basePath) {
416385
417110
  if (!partialPath) {
416386
417111
  const directory2 = basePath || getCwd();
@@ -416390,7 +417115,7 @@ function parsePartialPath(partialPath, basePath) {
416390
417115
  if (partialPath.endsWith("/") || partialPath.endsWith(sep30)) {
416391
417116
  return { directory: resolved, prefix: "" };
416392
417117
  }
416393
- const directory = dirname58(resolved);
417118
+ const directory = dirname59(resolved);
416394
417119
  const prefix = basename40(partialPath);
416395
417120
  return { directory, prefix };
416396
417121
  }
@@ -418319,7 +419044,7 @@ function Feedback({
418319
419044
  platform: env2.platform,
418320
419045
  gitRepo: envInfo.isGit,
418321
419046
  terminal: env2.terminal,
418322
- version: "1.65.10",
419047
+ version: "1.65.12",
418323
419048
  transcript: normalizeMessagesForAPI(messages),
418324
419049
  errors: sanitizedErrors,
418325
419050
  lastApiRequest: getLastAPIRequest(),
@@ -418511,7 +419236,7 @@ function Feedback({
418511
419236
  ", ",
418512
419237
  env2.terminal,
418513
419238
  ", v",
418514
- "1.65.10"
419239
+ "1.65.12"
418515
419240
  ]
418516
419241
  }, undefined, true, undefined, this)
418517
419242
  ]
@@ -418617,7 +419342,7 @@ ${sanitizedDescription}
418617
419342
  ` + `**Environment Info**
418618
419343
  ` + `- Platform: ${env2.platform}
418619
419344
  ` + `- Terminal: ${env2.terminal}
418620
- ` + `- Version: ${"1.65.10"}
419345
+ ` + `- Version: ${"1.65.12"}
418621
419346
  ` + `- Feedback ID: ${feedbackId}
418622
419347
  ` + `
418623
419348
  **Errors**
@@ -421727,7 +422452,7 @@ function buildPrimarySection() {
421727
422452
  }, undefined, false, undefined, this);
421728
422453
  return [{
421729
422454
  label: "Version",
421730
- value: "1.65.10"
422455
+ value: "1.65.12"
421731
422456
  }, {
421732
422457
  label: "Session name",
421733
422458
  value: nameValue
@@ -425057,7 +425782,7 @@ function Config({
425057
425782
  }
425058
425783
  }, undefined, false, undefined, this)
425059
425784
  }, undefined, false, undefined, this) : showSubmenu === "ChannelDowngrade" ? /* @__PURE__ */ jsx_dev_runtime179.jsxDEV(ChannelDowngradeDialog, {
425060
- currentVersion: "1.65.10",
425785
+ currentVersion: "1.65.12",
425061
425786
  onChoice: (choice) => {
425062
425787
  setShowSubmenu(null);
425063
425788
  setTabsHidden(false);
@@ -425069,7 +425794,7 @@ function Config({
425069
425794
  autoUpdatesChannel: "stable"
425070
425795
  };
425071
425796
  if (choice === "stay") {
425072
- newSettings.minimumVersion = "1.65.10";
425797
+ newSettings.minimumVersion = "1.65.12";
425073
425798
  }
425074
425799
  updateSettingsForSource("userSettings", newSettings);
425075
425800
  setSettingsData((prev_27) => ({
@@ -433133,7 +433858,7 @@ function HelpV2(t0) {
433133
433858
  let t6;
433134
433859
  if ($2[31] !== tabs) {
433135
433860
  t6 = /* @__PURE__ */ jsx_dev_runtime206.jsxDEV(Tabs, {
433136
- title: `UR v${"1.65.10"}`,
433861
+ title: `UR v${"1.65.12"}`,
433137
433862
  color: "professionalBlue",
433138
433863
  defaultTab: "general",
433139
433864
  children: tabs
@@ -434066,7 +434791,7 @@ function buildToolUseContext(tools, readFileStateCache, toolPermissionContext, a
434066
434791
  async function handleInitialize(options2) {
434067
434792
  return {
434068
434793
  name: "UR",
434069
- version: "1.65.10",
434794
+ version: "1.65.12",
434070
434795
  protocolVersion: "0.1.0",
434071
434796
  workspaceRoot: options2.cwd,
434072
434797
  capabilities: {
@@ -436108,7 +436833,7 @@ __export(exports_keybindings, {
436108
436833
  call: () => call24
436109
436834
  });
436110
436835
  import { mkdir as mkdir32, writeFile as writeFile34 } from "fs/promises";
436111
- import { dirname as dirname60 } from "path";
436836
+ import { dirname as dirname61 } from "path";
436112
436837
  async function call24() {
436113
436838
  if (!isKeybindingCustomizationEnabled()) {
436114
436839
  return {
@@ -436118,7 +436843,7 @@ async function call24() {
436118
436843
  }
436119
436844
  const keybindingsPath = getKeybindingsPath();
436120
436845
  let fileExists = false;
436121
- await mkdir32(dirname60(keybindingsPath), { recursive: true });
436846
+ await mkdir32(dirname61(keybindingsPath), { recursive: true });
436122
436847
  try {
436123
436848
  await writeFile34(keybindingsPath, generateKeybindingsTemplate(), {
436124
436849
  encoding: "utf-8",
@@ -443745,7 +444470,7 @@ var init_DiscoverPlugins = __esm(() => {
443745
444470
  });
443746
444471
 
443747
444472
  // src/services/plugins/pluginOperations.ts
443748
- import { dirname as dirname61, join as join142 } from "path";
444473
+ import { dirname as dirname62, join as join142 } from "path";
443749
444474
  function assertInstallableScope(scope) {
443750
444475
  if (!VALID_INSTALLABLE_SCOPES.includes(scope)) {
443751
444476
  throw new Error(`Invalid scope "${scope}". Must be one of: ${VALID_INSTALLABLE_SCOPES.join(", ")}`);
@@ -444222,7 +444947,7 @@ async function performPluginUpdate({
444222
444947
  }
444223
444948
  throw e;
444224
444949
  }
444225
- const marketplaceDir = marketplaceStats.isDirectory() ? marketplaceInstallLocation : dirname61(marketplaceInstallLocation);
444950
+ const marketplaceDir = marketplaceStats.isDirectory() ? marketplaceInstallLocation : dirname62(marketplaceInstallLocation);
444226
444951
  sourcePath = join142(marketplaceDir, entry.source);
444227
444952
  try {
444228
444953
  await fs4.stat(sourcePath);
@@ -451054,7 +451779,7 @@ ${args ? "Additional user input: " + args : ""}
451054
451779
 
451055
451780
  // src/utils/releaseNotes.ts
451056
451781
  import { mkdir as mkdir33, readFile as readFile45, writeFile as writeFile37 } from "fs/promises";
451057
- import { dirname as dirname63, join as join146 } from "path";
451782
+ import { dirname as dirname64, join as join146 } from "path";
451058
451783
  function getChangelogCachePath() {
451059
451784
  return join146(getURConfigHomeDir(), "cache", "changelog.md");
451060
451785
  }
@@ -451065,7 +451790,7 @@ async function migrateChangelogFromConfig() {
451065
451790
  }
451066
451791
  const cachePath = getChangelogCachePath();
451067
451792
  try {
451068
- await mkdir33(dirname63(cachePath), { recursive: true });
451793
+ await mkdir33(dirname64(cachePath), { recursive: true });
451069
451794
  await writeFile37(cachePath, config3.cachedChangelog, {
451070
451795
  encoding: "utf-8",
451071
451796
  flag: "wx"
@@ -451087,7 +451812,7 @@ async function fetchAndStoreChangelog() {
451087
451812
  return;
451088
451813
  }
451089
451814
  const cachePath = getChangelogCachePath();
451090
- await mkdir33(dirname63(cachePath), { recursive: true });
451815
+ await mkdir33(dirname64(cachePath), { recursive: true });
451091
451816
  await writeFile37(cachePath, changelogContent, { encoding: "utf-8" });
451092
451817
  changelogMemoryCache = changelogContent;
451093
451818
  const changelogLastFetched = Date.now();
@@ -451174,7 +451899,7 @@ function getAllReleaseNotes(changelogContent = getStoredChangelogFromMemory()) {
451174
451899
  return [];
451175
451900
  }
451176
451901
  }
451177
- async function checkForReleaseNotes(lastSeenVersion, currentVersion = "1.65.10") {
451902
+ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "1.65.12") {
451178
451903
  if (process.env.USER_TYPE === "ant") {
451179
451904
  const changelog = "";
451180
451905
  if (changelog) {
@@ -451201,7 +451926,7 @@ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "1.65.10")
451201
451926
  releaseNotes
451202
451927
  };
451203
451928
  }
451204
- function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "1.65.10") {
451929
+ function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "1.65.12") {
451205
451930
  if (process.env.USER_TYPE === "ant") {
451206
451931
  const changelog = "";
451207
451932
  if (changelog) {
@@ -454067,7 +454792,7 @@ function getRecentActivitySync() {
454067
454792
  return cachedActivity;
454068
454793
  }
454069
454794
  function getLogoDisplayData() {
454070
- const version2 = process.env.DEMO_VERSION ?? "1.65.10";
454795
+ const version2 = process.env.DEMO_VERSION ?? "1.65.12";
454071
454796
  const serverUrl = getDirectConnectServerUrl();
454072
454797
  const displayPath = process.env.DEMO_VERSION ? "/code/ur" : getDisplayPath(getCwd());
454073
454798
  const cwd2 = serverUrl ? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, "")}` : displayPath;
@@ -454934,7 +455659,7 @@ function LogoV2() {
454934
455659
  if ($2[2] === Symbol.for("react.memo_cache_sentinel")) {
454935
455660
  t2 = () => {
454936
455661
  const currentConfig2 = getGlobalConfig();
454937
- if (currentConfig2.lastReleaseNotesSeen === "1.65.10") {
455662
+ if (currentConfig2.lastReleaseNotesSeen === "1.65.12") {
454938
455663
  return;
454939
455664
  }
454940
455665
  saveGlobalConfig(_temp325);
@@ -455619,12 +456344,12 @@ function LogoV2() {
455619
456344
  return t41;
455620
456345
  }
455621
456346
  function _temp325(current) {
455622
- if (current.lastReleaseNotesSeen === "1.65.10") {
456347
+ if (current.lastReleaseNotesSeen === "1.65.12") {
455623
456348
  return current;
455624
456349
  }
455625
456350
  return {
455626
456351
  ...current,
455627
- lastReleaseNotesSeen: "1.65.10"
456352
+ lastReleaseNotesSeen: "1.65.12"
455628
456353
  };
455629
456354
  }
455630
456355
  function _temp241(s_0) {
@@ -461896,7 +462621,7 @@ import {
461896
462621
  readFileSync as readFileSync34,
461897
462622
  statSync as statSync14
461898
462623
  } from "fs";
461899
- import { dirname as dirname64, isAbsolute as isAbsolute33, resolve as resolve51 } from "path";
462624
+ import { dirname as dirname65, isAbsolute as isAbsolute33, resolve as resolve51 } from "path";
461900
462625
  function validateTranscriptContent(content) {
461901
462626
  const errors4 = [];
461902
462627
  let messageCount = 0;
@@ -461952,7 +462677,7 @@ function importSessionFile(sourcePath) {
461952
462677
  while (sessionIdExists(sessionId))
461953
462678
  sessionId = randomUUID46();
461954
462679
  const target = getTranscriptPathForSession(sessionId);
461955
- mkdirSync21(dirname64(target), { recursive: true });
462680
+ mkdirSync21(dirname65(target), { recursive: true });
461956
462681
  copyFileSync2(source, target);
461957
462682
  return { sessionId, path: target, messageCount: validation.messageCount };
461958
462683
  }
@@ -469587,7 +470312,7 @@ var init_attackSurface = __esm(() => {
469587
470312
 
469588
470313
  // src/security/findings.ts
469589
470314
  import * as fs7 from "fs";
469590
- import { dirname as dirname65, join as join151 } from "path";
470315
+ import { dirname as dirname66, join as join151 } from "path";
469591
470316
  function severityRank(s) {
469592
470317
  return ORDER.indexOf(s);
469593
470318
  }
@@ -469605,7 +470330,7 @@ class FindingStore {
469605
470330
  }
469606
470331
  }
469607
470332
  persist() {
469608
- fs7.mkdirSync(dirname65(this.file), { recursive: true });
470333
+ fs7.mkdirSync(dirname66(this.file), { recursive: true });
469609
470334
  fs7.writeFileSync(this.file, JSON.stringify(this.findings, null, 2));
469610
470335
  }
469611
470336
  add(items) {
@@ -471625,7 +472350,7 @@ import {
471625
472350
  writeFileSync as writeFileSync26
471626
472351
  } from "fs";
471627
472352
  import { tmpdir as tmpdir12 } from "os";
471628
- import { dirname as dirname66, isAbsolute as isAbsolute35, join as join157, relative as relative40, resolve as resolve55, sep as sep39 } from "path";
472353
+ import { dirname as dirname67, isAbsolute as isAbsolute35, join as join157, relative as relative40, resolve as resolve55, sep as sep39 } from "path";
471629
472354
  function positiveInteger(value, min, max2) {
471630
472355
  return typeof value === "number" && Number.isInteger(value) && value >= min && value <= max2;
471631
472356
  }
@@ -472156,7 +472881,7 @@ function manifestPathFor(dir, runId) {
472156
472881
  return join157(dir, runId, "manifest.json");
472157
472882
  }
472158
472883
  function writeAgenticCiResult(result) {
472159
- mkdirSync27(dirname66(result.manifestPath), { recursive: true });
472884
+ mkdirSync27(dirname67(result.manifestPath), { recursive: true });
472160
472885
  writeFileSync26(result.manifestPath, `${JSON.stringify(result, null, 2)}
472161
472886
  `, {
472162
472887
  mode: 384
@@ -472452,7 +473177,7 @@ async function runAgenticCi(options2) {
472452
473177
  let patch;
472453
473178
  if (diff2.trim() && violations.length === 0) {
472454
473179
  const digest3 = sha2562(diff2);
472455
- const runDir = dirname66(manifestPath5);
473180
+ const runDir = dirname67(manifestPath5);
472456
473181
  mkdirSync27(runDir, { recursive: true });
472457
473182
  const patchPath = join157(runDir, `patch-${digest3}.diff`);
472458
473183
  writeFileSync26(patchPath, diff2, { mode: 384 });
@@ -472548,7 +473273,7 @@ function saveAgenticCiSpec(cwd2, spec, options2 = {}) {
472548
473273
  if (!validation.valid)
472549
473274
  throw new Error(validation.errors.join("; "));
472550
473275
  const path22 = agenticCiSpecPath(cwd2, spec.name);
472551
- mkdirSync27(dirname66(path22), { recursive: true });
473276
+ mkdirSync27(dirname67(path22), { recursive: true });
472552
473277
  if (existsSync41(path22) && !options2.force)
472553
473278
  return { path: path22, created: false };
472554
473279
  writeFileSync26(path22, import_yaml3.stringify(spec), { mode: 384 });
@@ -472564,7 +473289,7 @@ function compileAgenticCiWorkflow(specName = "default", options2 = {}) {
472564
473289
  if (spec.name !== specName) {
472565
473290
  throw new Error("Agentic CI workflow spec name does not match");
472566
473291
  }
472567
- const packageVersion = options2.packageVersion ?? (typeof MACRO !== "undefined" ? "1.65.10" : "1.65.10");
473292
+ const packageVersion = options2.packageVersion ?? (typeof MACRO !== "undefined" ? "1.65.12" : "1.65.12");
472568
473293
  if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(packageVersion)) {
472569
473294
  throw new Error("invalid ur-agent package version");
472570
473295
  }
@@ -472903,12 +473628,12 @@ var init_agenticCi = __esm(() => {
472903
473628
 
472904
473629
  // src/services/agents/featureScaffolds.ts
472905
473630
  import { existsSync as existsSync42, mkdirSync as mkdirSync28, writeFileSync as writeFileSync27 } from "fs";
472906
- import { dirname as dirname67, join as join158 } from "path";
473631
+ import { dirname as dirname68, join as join158 } from "path";
472907
473632
  function writeSeedFile(root2, file2, result, force) {
472908
- const baseRoot = file2.root === "project" ? dirname67(root2) : root2;
473633
+ const baseRoot = file2.root === "project" ? dirname68(root2) : root2;
472909
473634
  const fullPath = join158(baseRoot, file2.path);
472910
473635
  const displayPath = file2.path;
472911
- mkdirSync28(dirname67(fullPath), { recursive: true });
473636
+ mkdirSync28(dirname68(fullPath), { recursive: true });
472912
473637
  if (!force && existsSync42(fullPath)) {
472913
473638
  result.skipped.push(displayPath);
472914
473639
  return;
@@ -473557,7 +474282,7 @@ runner; \`ur trigger\` is the inbound parser that decides what to run.
473557
474282
  path: ".github/workflows/ur.yml",
473558
474283
  root: "project",
473559
474284
  content: compileAgenticCiWorkflow("default", {
473560
- packageVersion: typeof MACRO !== "undefined" ? "1.65.10" : "1.65.10"
474285
+ packageVersion: typeof MACRO !== "undefined" ? "1.65.12" : "1.65.12"
473561
474286
  })
473562
474287
  },
473563
474288
  {
@@ -473621,13 +474346,13 @@ __export(exports_agent_ci, {
473621
474346
  call: () => call56
473622
474347
  });
473623
474348
  import { existsSync as existsSync43, mkdirSync as mkdirSync29, writeFileSync as writeFileSync28 } from "fs";
473624
- import { dirname as dirname68, join as join159 } from "path";
474349
+ import { dirname as dirname69, join as join159 } from "path";
473625
474350
  function value(tokens, flag) {
473626
474351
  const index2 = tokens.indexOf(flag);
473627
474352
  return index2 >= 0 ? tokens[index2 + 1] : undefined;
473628
474353
  }
473629
474354
  function cliVersion() {
473630
- return typeof MACRO !== "undefined" ? "1.65.10" : "1.65.10";
474355
+ return typeof MACRO !== "undefined" ? "1.65.12" : "1.65.12";
473631
474356
  }
473632
474357
  function workflowPath(cwd2) {
473633
474358
  return join159(cwd2, ".github", "workflows", "ur-agentic-ci.yml");
@@ -473685,7 +474410,7 @@ var call56 = async (args) => {
473685
474410
  const target = workflowPath(cwd2);
473686
474411
  let workflowCreated = false;
473687
474412
  if (!existsSync43(target) || force) {
473688
- mkdirSync29(dirname68(target), { recursive: true });
474413
+ mkdirSync29(dirname69(target), { recursive: true });
473689
474414
  writeFileSync28(target, compileAgenticCiWorkflow(name, {
473690
474415
  packageVersion: cliVersion(),
473691
474416
  spec: compiledSpec
@@ -473730,7 +474455,7 @@ Use --force to replace it.`
473730
474455
  value: json2 ? JSON.stringify(result, null, 2) : `${result.replacing ? "Would replace" : "Would write"} hardened workflow at ${target}`
473731
474456
  };
473732
474457
  }
473733
- mkdirSync29(dirname68(target), { recursive: true });
474458
+ mkdirSync29(dirname69(target), { recursive: true });
473734
474459
  writeFileSync28(target, compileAgenticCiWorkflow(name, {
473735
474460
  packageVersion: cliVersion(),
473736
474461
  spec: workflowSpec
@@ -479492,7 +480217,7 @@ function createAcpStdioApp(deps) {
479492
480217
  }
479493
480218
  },
479494
480219
  authMethods: [],
479495
- agentInfo: { name: "UR-Nexus", version: "1.65.10" }
480220
+ agentInfo: { name: "UR-Nexus", version: "1.65.12" }
479496
480221
  })).onRequest("authenticate", () => ({})).onRequest("session/new", async (context6) => {
479497
480222
  const result = runtime2.newSession(context6.params.cwd, context6.params.mcpServers, context6.params.additionalDirectories);
479498
480223
  await runtime2.announce({
@@ -479589,7 +480314,7 @@ function createAcpStdioAgent(deps) {
479589
480314
  }
479590
480315
  },
479591
480316
  authMethods: [],
479592
- agentInfo: { name: "UR-Nexus", version: "1.65.10" }
480317
+ agentInfo: { name: "UR-Nexus", version: "1.65.12" }
479593
480318
  });
479594
480319
  return;
479595
480320
  case "authenticate":
@@ -481362,7 +482087,7 @@ var init_validation5 = () => {};
481362
482087
 
481363
482088
  // src/services/promptPlanning/executor.ts
481364
482089
  import { realpathSync as realpathSync13 } from "fs";
481365
- import { basename as basename45, dirname as dirname69, resolve as resolve56 } from "path";
482090
+ import { basename as basename45, dirname as dirname70, resolve as resolve56 } from "path";
481366
482091
  function cloneTasks(tasks2) {
481367
482092
  return tasks2.map((task) => ({
481368
482093
  ...task,
@@ -481394,7 +482119,7 @@ function canonicalLockKey(cwd2, value2) {
481394
482119
  const suffix = [];
481395
482120
  let current = absolute;
481396
482121
  for (;; ) {
481397
- const parent2 = dirname69(current);
482122
+ const parent2 = dirname70(current);
481398
482123
  if (parent2 === current)
481399
482124
  return absolute;
481400
482125
  suffix.unshift(basename45(current));
@@ -482643,7 +483368,7 @@ function buildExecFinalReport(run3) {
482643
483368
  ]
482644
483369
  };
482645
483370
  }
482646
- function formatList(items, empty, render2) {
483371
+ function formatList2(items, empty, render2) {
482647
483372
  return items.length > 0 ? items.map(render2) : [`- ${empty}`];
482648
483373
  }
482649
483374
  function formatApprovalDecision(decision) {
@@ -482670,46 +483395,46 @@ function formatExecFinalReport(report) {
482670
483395
  `Agents used: ${report.activeAgentsUsed} active / ${report.maxAgentsAllowed} max`,
482671
483396
  "",
482672
483397
  "Finished tasks:",
482673
- ...formatList(report.finishedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
483398
+ ...formatList2(report.finishedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
482674
483399
  "",
482675
483400
  "Failed tasks:",
482676
- ...formatList(report.failedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
483401
+ ...formatList2(report.failedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
482677
483402
  "",
482678
483403
  "Waiting on prerequisite tasks:",
482679
- ...formatList(report.blockedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
483404
+ ...formatList2(report.blockedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
482680
483405
  "",
482681
483406
  "Waiting approval/input tasks:",
482682
- ...formatList(report.waitingApprovalTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
483407
+ ...formatList2(report.waitingApprovalTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
482683
483408
  "",
482684
483409
  "Skipped tasks:",
482685
- ...formatList(report.skippedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
483410
+ ...formatList2(report.skippedTasks, "none", (task) => `- ${task.id} | ${task.agent} | ${task.title}`),
482686
483411
  "",
482687
483412
  "Actual changed files:",
482688
- ...formatList(report.actualChangedFiles, "none observed", (file2) => `- ${file2}`),
483413
+ ...formatList2(report.actualChangedFiles, "none observed", (file2) => `- ${file2}`),
482689
483414
  "",
482690
483415
  "Outside-workspace files accessed:",
482691
- ...formatList(report.outsideWorkspaceFilesAccessed, "none observed", (file2) => `- ${file2}`),
483416
+ ...formatList2(report.outsideWorkspaceFilesAccessed, "none observed", (file2) => `- ${file2}`),
482692
483417
  "",
482693
483418
  "Outside-workspace files modified:",
482694
- ...formatList(report.outsideWorkspaceFilesModified, "none observed", (file2) => `- ${file2}`),
483419
+ ...formatList2(report.outsideWorkspaceFilesModified, "none observed", (file2) => `- ${file2}`),
482695
483420
  "",
482696
483421
  "Unreported changed files:",
482697
- ...formatList(report.unreportedChangedFiles, "none", (file2) => `- ${file2}`),
483422
+ ...formatList2(report.unreportedChangedFiles, "none", (file2) => `- ${file2}`),
482698
483423
  "",
482699
483424
  "Verified commands:",
482700
- ...formatList(report.verifiedCommands, "none observed", (command5) => `- ${command5}`),
483425
+ ...formatList2(report.verifiedCommands, "none observed", (command5) => `- ${command5}`),
482701
483426
  "",
482702
483427
  "Unverified command claims:",
482703
- ...formatList(report.unverifiedCommandClaims, "none", (command5) => `- ${command5}`),
483428
+ ...formatList2(report.unverifiedCommandClaims, "none", (command5) => `- ${command5}`),
482704
483429
  "",
482705
483430
  "Approval decisions:",
482706
- ...formatList(report.approvalDecisions, "none", formatApprovalDecision),
483431
+ ...formatList2(report.approvalDecisions, "none", formatApprovalDecision),
482707
483432
  "",
482708
483433
  "Verification failures:",
482709
- ...formatList(report.verificationFailures, "none", (failure) => `- ${failure.taskId} | ${failure.code} | ${failure.message}`),
483434
+ ...formatList2(report.verificationFailures, "none", (failure) => `- ${failure.taskId} | ${failure.code} | ${failure.message}`),
482710
483435
  "",
482711
483436
  "Warnings:",
482712
- ...formatList(report.warnings, "none", (warning) => `- ${warning.taskId} | ${warning.code} | ${warning.message}`),
483437
+ ...formatList2(report.warnings, "none", (warning) => `- ${warning.taskId} | ${warning.code} | ${warning.message}`),
482713
483438
  "",
482714
483439
  "Remaining limitations:",
482715
483440
  ...report.remainingLimitations.map((item) => `- ${item}`)
@@ -486013,7 +486738,7 @@ import {
486013
486738
  writeFileSync as writeFileSync36
486014
486739
  } from "fs";
486015
486740
  import { homedir as homedir32 } from "os";
486016
- import { dirname as dirname70, isAbsolute as isAbsolute39, join as join171, resolve as resolve58, sep as pathSep3 } from "path";
486741
+ import { dirname as dirname71, isAbsolute as isAbsolute39, join as join171, resolve as resolve58, sep as pathSep3 } from "path";
486017
486742
  function parseCommandTokens(tokens) {
486018
486743
  const positional = [];
486019
486744
  const flags = new Set;
@@ -486081,7 +486806,7 @@ function readPrivateKey(path22) {
486081
486806
  }
486082
486807
  function writeTrustedKeys(keys2) {
486083
486808
  const path22 = trustedSkillKeysPath();
486084
- mkdirSync37(dirname70(path22), { recursive: true, mode: 448 });
486809
+ mkdirSync37(dirname71(path22), { recursive: true, mode: 448 });
486085
486810
  const temporary = `${path22}.${process.pid}.${randomUUID52()}.tmp`;
486086
486811
  try {
486087
486812
  writeFileSync36(temporary, `${JSON.stringify(keys2, null, 2)}
@@ -486164,7 +486889,7 @@ var VALUE_OPTIONS, call70 = async (args) => {
486164
486889
  const { privateKey, publicKey } = generateKeyPairSync2("ed25519");
486165
486890
  const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
486166
486891
  const publicPem = publicKey.export({ type: "spki", format: "pem" }).toString();
486167
- mkdirSync37(dirname70(privatePath), { recursive: true, mode: 448 });
486892
+ mkdirSync37(dirname71(privatePath), { recursive: true, mode: 448 });
486168
486893
  writeFileSync36(privatePath, privatePem, { flag: "wx", mode: 384 });
486169
486894
  createdPrivate = true;
486170
486895
  writeFileSync36(publicPath, publicPem, { flag: "wx", mode: 420 });
@@ -487134,7 +487859,7 @@ import {
487134
487859
  writeFileSync as writeFileSync39
487135
487860
  } from "fs";
487136
487861
  import { tmpdir as tmpdir14 } from "os";
487137
- import { dirname as dirname71, join as join175 } from "path";
487862
+ import { dirname as dirname72, join as join175 } from "path";
487138
487863
  function redactArenaText(value2) {
487139
487864
  return redactAgenticCiText(value2);
487140
487865
  }
@@ -487608,7 +488333,7 @@ async function applyWinner(cwd2, baseSha, runId, winner) {
487608
488333
  }
487609
488334
  const digest3 = sha2563(winner.diff);
487610
488335
  const patch = join175(cwd2, ".ur", "arena", runId, `winner-${digest3}.patch`);
487611
- mkdirSync39(dirname71(patch), { recursive: true });
488336
+ mkdirSync39(dirname72(patch), { recursive: true });
487612
488337
  writeFileSync39(patch, winner.diff, { mode: 384 });
487613
488338
  const check3 = await git4(cwd2, ["apply", "--check", "--3way", patch]);
487614
488339
  if (check3.code !== 0) {
@@ -490347,17 +491072,17 @@ __export(exports_agent_inspect, {
490347
491072
  call: () => call78
490348
491073
  });
490349
491074
  import { readdirSync as readdirSync23, statSync as statSync23 } from "fs";
490350
- import { dirname as dirname72, join as join183 } from "path";
491075
+ import { dirname as dirname73, join as join183 } from "path";
490351
491076
  function resolveSessionSubagentsDir() {
490352
491077
  let live;
490353
491078
  try {
490354
- live = dirname72(getAgentTranscriptPath("probe"));
491079
+ live = dirname73(getAgentTranscriptPath("probe"));
490355
491080
  } catch {
490356
491081
  return null;
490357
491082
  }
490358
491083
  if (hasTranscripts(live))
490359
491084
  return live;
490360
- const projectDir = dirname72(dirname72(live));
491085
+ const projectDir = dirname73(dirname73(live));
490361
491086
  let sessions;
490362
491087
  try {
490363
491088
  sessions = readdirSync23(projectDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join183(projectDir, entry.name, "subagents")).filter(hasTranscripts);
@@ -490701,7 +491426,7 @@ var init_memoryIntegrity = __esm(() => {
490701
491426
  });
490702
491427
 
490703
491428
  // src/memdir/teamMemPaths.ts
490704
- import { dirname as dirname73, join as join185, resolve as resolve60, sep as sep43 } from "path";
491429
+ import { dirname as dirname74, join as join185, resolve as resolve60, sep as sep43 } from "path";
490705
491430
  function getTeamMemPath() {
490706
491431
  return (join185(getAutoMemPath(), "team") + sep43).normalize("NFC");
490707
491432
  }
@@ -496982,7 +497707,7 @@ import {
496982
497707
  writeFileSync as writeFileSync54
496983
497708
  } from "fs";
496984
497709
  import {
496985
- dirname as dirname74,
497710
+ dirname as dirname75,
496986
497711
  isAbsolute as isAbsolute43,
496987
497712
  join as join198,
496988
497713
  relative as relative48,
@@ -497027,7 +497752,7 @@ function existingAncestor(path22) {
497027
497752
  for (;; ) {
497028
497753
  if (existsSync77(current))
497029
497754
  return realpathSync15(current);
497030
- const parent2 = dirname74(current);
497755
+ const parent2 = dirname75(current);
497031
497756
  if (parent2 === current)
497032
497757
  return current;
497033
497758
  current = parent2;
@@ -497037,7 +497762,7 @@ function initTargetAllowed(cwd2, path22, allowExternal) {
497037
497762
  if (allowExternal)
497038
497763
  return true;
497039
497764
  const workspace = realpathSync15(cwd2);
497040
- return pathIsWithin4(workspace, resolve64(path22)) && pathIsWithin4(workspace, existingAncestor(dirname74(path22)));
497765
+ return pathIsWithin4(workspace, resolve64(path22)) && pathIsWithin4(workspace, existingAncestor(dirname75(path22)));
497041
497766
  }
497042
497767
  async function runDesktopQaCommand(args, cwd2, dependencies = {}) {
497043
497768
  const runFixture = dependencies.runFixture ?? runDesktopQaFixture;
@@ -497127,7 +497852,7 @@ async function runDesktopQaCommand(args, cwd2, dependencies = {}) {
497127
497852
  value: `Fixture already exists: ${path22} (use --force to replace it).`
497128
497853
  };
497129
497854
  }
497130
- mkdirSync54(dirname74(path22), { recursive: true, mode: 448 });
497855
+ mkdirSync54(dirname75(path22), { recursive: true, mode: 448 });
497131
497856
  writeFileSync54(path22, `${JSON.stringify(EXAMPLE_FIXTURE, null, 2)}
497132
497857
  `, {
497133
497858
  mode: 384
@@ -498011,7 +498736,7 @@ import {
498011
498736
  readFileSync as readFileSync72,
498012
498737
  writeFileSync as writeFileSync55
498013
498738
  } from "fs";
498014
- import { dirname as dirname75, join as join199, relative as relative49 } from "path";
498739
+ import { dirname as dirname76, join as join199, relative as relative49 } from "path";
498015
498740
  function defaultTraceDir(cwd2) {
498016
498741
  return join199(cwd2, ".ur", "test-first", "traces");
498017
498742
  }
@@ -498064,7 +498789,7 @@ function mergeStringArray(existing2, additions) {
498064
498789
  }
498065
498790
  function installTestFirstGates(cwd2, stack = detectTestFirstStack(cwd2)) {
498066
498791
  const path22 = join199(cwd2, ".ur", "verify.json");
498067
- mkdirSync55(dirname75(path22), { recursive: true });
498792
+ mkdirSync55(dirname76(path22), { recursive: true });
498068
498793
  const commands = stack.commands.map((command5) => command5.command);
498069
498794
  const existing2 = readExistingVerifyConfig(path22);
498070
498795
  const next = {
@@ -502475,7 +503200,7 @@ var init_os2 = __esm(() => {
502475
503200
  import { createHash as createHash47, randomUUID as randomUUID59 } from "crypto";
502476
503201
  import { existsSync as existsSync83, lstatSync as lstatSync20, realpathSync as realpathSync16, rmSync as rmSync18 } from "fs";
502477
503202
  import { tmpdir as tmpdir16 } from "os";
502478
- import { dirname as dirname76, isAbsolute as isAbsolute44, join as join204, relative as relative50, resolve as resolve66 } from "path";
503203
+ import { dirname as dirname77, isAbsolute as isAbsolute44, join as join204, relative as relative50, resolve as resolve66 } from "path";
502479
503204
  function workspaceDir(cwd2) {
502480
503205
  return join204(cwd2, ".ur", "workspaces");
502481
503206
  }
@@ -502884,7 +503609,7 @@ async function prepareRepositoryState(cwd2, spec2, validation, runId, options3)
502884
503609
  if (filters.code !== 0 && filters.code !== 1) {
502885
503610
  throw new Error(`Could not inspect ${repo.id} Git filters`);
502886
503611
  }
502887
- ensurePrivateDirectory(workspaceDir(cwd2), dirname76(worktree2));
503612
+ ensurePrivateDirectory(workspaceDir(cwd2), dirname77(worktree2));
502888
503613
  const created = await git7(details.root, ["worktree", "add", "-b", branch, worktree2, repo.baseRef], options3.commandRunner);
502889
503614
  if (created.code !== 0) {
502890
503615
  throw new Error(`Could not create ${repo.id} worktree: ${created.stderr || created.error || created.stdout}`);
@@ -502981,7 +503706,7 @@ async function runWorkspace(cwd2, name, options3 = {}) {
502981
503706
  const persist = () => {
502982
503707
  state.updatedAt = new Date().toISOString();
502983
503708
  if (!options3.dryRun) {
502984
- ensurePrivateDirectory(workspaceDir(cwd2), dirname76(workspaceStatePath(cwd2, name)));
503709
+ ensurePrivateDirectory(workspaceDir(cwd2), dirname77(workspaceStatePath(cwd2, name)));
502985
503710
  withPrivateStateLock(workspaceDir(cwd2), `state-${name}`, () => saveState(cwd2, state));
502986
503711
  }
502987
503712
  };
@@ -503642,7 +504367,7 @@ import {
503642
504367
  readdirSync as readdirSync32,
503643
504368
  writeFileSync as writeFileSync59
503644
504369
  } from "fs";
503645
- import { dirname as dirname77, join as join205 } from "path";
504370
+ import { dirname as dirname78, join as join205 } from "path";
503646
504371
  function memoryDir(cwd2) {
503647
504372
  return join205(cwd2, ".ur", "memory");
503648
504373
  }
@@ -503677,7 +504402,7 @@ function saveMemoryRetentionPolicy(cwd2, patch) {
503677
504402
  decayDays: patch.decayDays === undefined ? current.decayDays : validPositive(patch.decayDays),
503678
504403
  updatedAt: new Date().toISOString()
503679
504404
  };
503680
- mkdirSync59(dirname77(policyPath2(cwd2)), { recursive: true });
504405
+ mkdirSync59(dirname78(policyPath2(cwd2)), { recursive: true });
503681
504406
  writeFileSync59(policyPath2(cwd2), `${JSON.stringify(next, null, 2)}
503682
504407
  `);
503683
504408
  return next;
@@ -673368,7 +674093,7 @@ import {
673368
674093
  statSync as statSync29,
673369
674094
  writeFileSync as writeFileSync61
673370
674095
  } from "fs";
673371
- import { dirname as dirname78, extname as extname19, isAbsolute as isAbsolute45, join as join207, relative as relative52, resolve as resolve67 } from "path";
674096
+ import { dirname as dirname79, extname as extname19, isAbsolute as isAbsolute45, join as join207, relative as relative52, resolve as resolve67 } from "path";
673372
674097
  import { promisify as promisify4 } from "util";
673373
674098
  function repoEditIndexPath(root2) {
673374
674099
  return join207(root2, ".ur", "repo-edit", "index.json");
@@ -673508,7 +674233,7 @@ ${content}`),
673508
674233
  builtAt: new Date().toISOString(),
673509
674234
  files
673510
674235
  };
673511
- mkdirSync61(dirname78(repoEditIndexPath(root2)), { recursive: true });
674236
+ mkdirSync61(dirname79(repoEditIndexPath(root2)), { recursive: true });
673512
674237
  writeFileSync61(repoEditIndexPath(root2), `${JSON.stringify(index2, null, 2)}
673513
674238
  `);
673514
674239
  return index2;
@@ -674185,7 +674910,7 @@ var init_diagnostics = __esm(() => {
674185
674910
  });
674186
674911
 
674187
674912
  // src/services/repoEditing/ast/workspaceEdit.ts
674188
- import { dirname as dirname79, isAbsolute as isAbsolute46, relative as relative53, resolve as resolve68, sep as sep47 } from "path";
674913
+ import { dirname as dirname80, isAbsolute as isAbsolute46, relative as relative53, resolve as resolve68, sep as sep47 } from "path";
674189
674914
  import {
674190
674915
  chmodSync as chmodSync11,
674191
674916
  existsSync as existsSync87,
@@ -674236,7 +674961,7 @@ function realpathForMissing(path22) {
674236
674961
  const suffix = [];
674237
674962
  let cursor = path22;
674238
674963
  while (!existsSync87(cursor)) {
674239
- const parent2 = dirname79(cursor);
674964
+ const parent2 = dirname80(cursor);
674240
674965
  if (parent2 === cursor)
674241
674966
  return path22;
674242
674967
  suffix.unshift(cursor.slice(parent2.length + (parent2.endsWith(sep47) ? 0 : 1)));
@@ -674266,8 +674991,8 @@ function workspaceRelativePath(root2, file2) {
674266
674991
  return relative53(realpathSync17(root2), resolveWorkspaceFile(root2, file2)).split(sep47).join("/");
674267
674992
  }
674268
674993
  function atomicWrite(path22, content, mode) {
674269
- mkdirSync62(dirname79(path22), { recursive: true });
674270
- const temp = resolve68(dirname79(path22), `.${randomUUID60()}.ur-repo-edit.tmp`);
674994
+ mkdirSync62(dirname80(path22), { recursive: true });
674995
+ const temp = resolve68(dirname80(path22), `.${randomUUID60()}.ur-repo-edit.tmp`);
674271
674996
  try {
674272
674997
  writeFileSync62(temp, content, { flag: "wx", ...mode !== undefined ? { mode } : {} });
674273
674998
  renameSync17(temp, path22);
@@ -674316,14 +675041,14 @@ function rollbackWorkspaceEdit(root2, snapshots) {
674316
675041
  continue;
674317
675042
  }
674318
675043
  rmSync19(abs, { force: true, recursive: true });
674319
- let parent2 = dirname79(abs);
675044
+ let parent2 = dirname80(abs);
674320
675045
  while (parent2 !== realRoot && isWithin(realRoot, parent2)) {
674321
675046
  try {
674322
675047
  rmdirSync2(parent2);
674323
675048
  } catch {
674324
675049
  break;
674325
675050
  }
674326
- parent2 = dirname79(parent2);
675051
+ parent2 = dirname80(parent2);
674327
675052
  }
674328
675053
  }
674329
675054
  }
@@ -674471,7 +675196,7 @@ var init_lspEditEngine = __esm(() => {
674471
675196
  });
674472
675197
 
674473
675198
  // src/services/repoEditing/ast/typescriptEngine.ts
674474
- import { dirname as dirname80, join as join209, relative as relative54 } from "path";
675199
+ import { dirname as dirname81, join as join209, relative as relative54 } from "path";
674475
675200
  import { existsSync as existsSync88, readFileSync as readFileSync81 } from "fs";
674476
675201
  function loadProgram(root2, files) {
674477
675202
  const configPath2 = import_typescript3.default.findConfigFile(root2, import_typescript3.default.sys.fileExists, "tsconfig.json");
@@ -674732,11 +675457,11 @@ function normalizePath4(value2) {
674732
675457
  function resolveRelativeImport(importingFileRel, specifier) {
674733
675458
  if (!specifier.startsWith("."))
674734
675459
  return;
674735
- const base2 = normalizePath4(join209(dirname80(importingFileRel), specifier));
675460
+ const base2 = normalizePath4(join209(dirname81(importingFileRel), specifier));
674736
675461
  return stripKnownExtension(base2);
674737
675462
  }
674738
675463
  function moduleSpecifierBetween(importingFileRel, targetFileRel) {
674739
- let specifier = normalizePath4(relative54(dirname80(importingFileRel), stripKnownExtension(targetFileRel)));
675464
+ let specifier = normalizePath4(relative54(dirname81(importingFileRel), stripKnownExtension(targetFileRel)));
674740
675465
  if (!specifier.startsWith("."))
674741
675466
  specifier = `./${specifier}`;
674742
675467
  return specifier;
@@ -676702,7 +677427,7 @@ __export(exports_role_mode, {
676702
677427
  });
676703
677428
  import { existsSync as existsSync94, mkdirSync as mkdirSync65, writeFileSync as writeFileSync65 } from "fs";
676704
677429
  import { join as join212 } from "path";
676705
- function formatList2() {
677430
+ function formatList3() {
676706
677431
  const lines = ["Built-in role modes:", ""];
676707
677432
  for (const mode2 of ROLE_MODES) {
676708
677433
  const scope = mode2.tools ? mode2.tools.join(", ") : "all tools";
@@ -676733,7 +677458,7 @@ var call127 = async (args) => {
676733
677458
  })), null, 2)
676734
677459
  };
676735
677460
  }
676736
- return { type: "text", value: formatList2() };
677461
+ return { type: "text", value: formatList3() };
676737
677462
  }
676738
677463
  if (command5 === "show") {
676739
677464
  const name = positional2[1];
@@ -690749,7 +691474,7 @@ async function captureMemoryDiagnostics(trigger2, dumpNumber = 0) {
690749
691474
  smapsRollup,
690750
691475
  platform: process.platform,
690751
691476
  nodeVersion: process.version,
690752
- ccVersion: "1.65.10"
691477
+ ccVersion: "1.65.12"
690753
691478
  };
690754
691479
  }
690755
691480
  async function performHeapDump(trigger2 = "manual", dumpNumber = 0) {
@@ -691329,7 +692054,7 @@ var init_bridge_kick = __esm(() => {
691329
692054
  var call153 = async () => {
691330
692055
  return {
691331
692056
  type: "text",
691332
- value: "1.65.10"
692057
+ value: "1.65.12"
691333
692058
  };
691334
692059
  }, version2, version_default;
691335
692060
  var init_version = __esm(() => {
@@ -693516,7 +694241,7 @@ var init_advisor2 = __esm(() => {
693516
694241
  // src/skills/bundledSkills.ts
693517
694242
  import { constants as fsConstants6 } from "fs";
693518
694243
  import { mkdir as mkdir38, open as open15 } from "fs/promises";
693519
- import { dirname as dirname81, isAbsolute as isAbsolute52, join as join223, normalize as normalize16, sep as pathSep4 } from "path";
694244
+ import { dirname as dirname82, isAbsolute as isAbsolute52, join as join223, normalize as normalize16, sep as pathSep4 } from "path";
693520
694245
  function registerBundledSkill(definition) {
693521
694246
  const { files: files2 } = definition;
693522
694247
  let skillRoot;
@@ -693580,7 +694305,7 @@ async function writeSkillFiles(dir, files2) {
693580
694305
  const byParent = new Map;
693581
694306
  for (const [relPath, content] of Object.entries(files2)) {
693582
694307
  const target = resolveSkillFilePath(dir, relPath);
693583
- const parent2 = dirname81(target);
694308
+ const parent2 = dirname82(target);
693584
694309
  const entry = [target, content];
693585
694310
  const group = byParent.get(parent2);
693586
694311
  if (group)
@@ -693963,7 +694688,7 @@ var init_exit2 = __esm(() => {
693963
694688
  // src/utils/exportPath.ts
693964
694689
  import { existsSync as existsSync99, lstatSync as lstatSync23, realpathSync as realpathSync22 } from "fs";
693965
694690
  import {
693966
- dirname as dirname82,
694691
+ dirname as dirname83,
693967
694692
  extname as extname23,
693968
694693
  isAbsolute as isAbsolute53,
693969
694694
  relative as relative61,
@@ -694001,7 +694726,7 @@ function resolveExportPath(cwd2, input) {
694001
694726
  const root2 = realpathSync22(cwd2);
694002
694727
  const filename = normalizeExportFilename(trimmed);
694003
694728
  const target = resolve73(root2, filename);
694004
- const parent2 = realpathSync22(dirname82(target));
694729
+ const parent2 = realpathSync22(dirname83(target));
694005
694730
  if (escapes(root2, parent2)) {
694006
694731
  throw new Error("Export path resolves outside the workspace");
694007
694732
  }
@@ -702509,7 +703234,7 @@ function generateHtmlReport(data, insights) {
702509
703234
  </html>`;
702510
703235
  }
702511
703236
  function buildExportData(data, insights, facets, remoteStats) {
702512
- const version3 = typeof MACRO !== "undefined" ? "1.65.10" : "unknown";
703237
+ const version3 = typeof MACRO !== "undefined" ? "1.65.12" : "unknown";
702513
703238
  const remote_hosts_collected = remoteStats?.hosts.filter((h2) => h2.sessionCount > 0).map((h2) => h2.name);
702514
703239
  const facets_summary = {
702515
703240
  total: facets.size,
@@ -703971,7 +704696,7 @@ import {
703971
704696
  unlink as unlink23,
703972
704697
  writeFile as writeFile44
703973
704698
  } from "fs/promises";
703974
- import { basename as basename51, dirname as dirname84, join as join228 } from "path";
704699
+ import { basename as basename51, dirname as dirname85, join as join228 } from "path";
703975
704700
  function isTranscriptMessage(entry) {
703976
704701
  const t = entry.type;
703977
704702
  return t === "user" || t === "assistant" || t === "attachment" || t === "system";
@@ -704020,7 +704745,7 @@ function getAgentMetadataPath(agentId) {
704020
704745
  }
704021
704746
  async function writeAgentMetadata(agentId, metadata) {
704022
704747
  const path22 = getAgentMetadataPath(agentId);
704023
- await mkdir41(dirname84(path22), { recursive: true });
704748
+ await mkdir41(dirname85(path22), { recursive: true });
704024
704749
  await writeFile44(path22, JSON.stringify(metadata));
704025
704750
  }
704026
704751
  async function readAgentMetadata(agentId) {
@@ -704043,7 +704768,7 @@ function getRemoteAgentMetadataPath(taskId) {
704043
704768
  }
704044
704769
  async function writeRemoteAgentMetadata(taskId, metadata) {
704045
704770
  const path22 = getRemoteAgentMetadataPath(taskId);
704046
- await mkdir41(dirname84(path22), { recursive: true });
704771
+ await mkdir41(dirname85(path22), { recursive: true });
704047
704772
  await writeFile44(path22, JSON.stringify(metadata));
704048
704773
  }
704049
704774
  async function readRemoteAgentMetadata(taskId) {
@@ -704251,7 +704976,7 @@ class Project {
704251
704976
  try {
704252
704977
  await fsAppendFile(filePath, data, { mode: 384 });
704253
704978
  } catch {
704254
- await mkdir41(dirname84(filePath), { recursive: true, mode: 448 });
704979
+ await mkdir41(dirname85(filePath), { recursive: true, mode: 448 });
704255
704980
  await fsAppendFile(filePath, data, { mode: 384 });
704256
704981
  }
704257
704982
  }
@@ -704865,7 +705590,7 @@ async function hydrateFromCCRv2InternalEvents(sessionId) {
704865
705590
  }
704866
705591
  for (const [agentId, entries] of byAgent) {
704867
705592
  const agentFile = getAgentTranscriptPath(asAgentId(agentId));
704868
- await mkdir41(dirname84(agentFile), { recursive: true, mode: 448 });
705593
+ await mkdir41(dirname85(agentFile), { recursive: true, mode: 448 });
704869
705594
  const agentContent = entries.map((p2) => jsonStringify(p2) + `
704870
705595
  `).join("");
704871
705596
  await writeFile44(agentFile, agentContent, {
@@ -705402,7 +706127,7 @@ function appendEntryToFile(fullPath, entry) {
705402
706127
  try {
705403
706128
  fs12.appendFileSync(fullPath, line, { mode: 384 });
705404
706129
  } catch {
705405
- fs12.mkdirSync(dirname84(fullPath), { mode: 448 });
706130
+ fs12.mkdirSync(dirname85(fullPath), { mode: 448 });
705406
706131
  fs12.appendFileSync(fullPath, line, { mode: 384 });
705407
706132
  }
705408
706133
  }
@@ -706836,7 +707561,7 @@ var init_sessionStorage = __esm(() => {
706836
707561
  init_settings2();
706837
707562
  init_slowOperations();
706838
707563
  init_uuid();
706839
- VERSION7 = typeof MACRO !== "undefined" ? "1.65.10" : "unknown";
707564
+ VERSION7 = typeof MACRO !== "undefined" ? "1.65.12" : "unknown";
706840
707565
  MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
706841
707566
  SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
706842
707567
  EPHEMERAL_PROGRESS_TYPES = new Set([
@@ -708051,7 +708776,7 @@ var init_filesystem = __esm(() => {
708051
708776
  });
708052
708777
  getBundledSkillsRoot = memoize_default(function getBundledSkillsRoot2() {
708053
708778
  const nonce = randomBytes20(16).toString("hex");
708054
- return join230(getURTempDir(), "bundled-skills", "1.65.10", nonce);
708779
+ return join230(getURTempDir(), "bundled-skills", "1.65.12", nonce);
708055
708780
  });
708056
708781
  getResolvedWorkingDirPaths = memoize_default(getPathsForPermissionCheck);
708057
708782
  });
@@ -712619,7 +713344,7 @@ import {
712619
713344
  symlink as symlink5,
712620
713345
  utimes as utimes2
712621
713346
  } from "fs/promises";
712622
- import { basename as basename53, dirname as dirname85, join as join232 } from "path";
713347
+ import { basename as basename53, dirname as dirname86, join as join232 } from "path";
712623
713348
  function validateWorktreeSlug(slug5) {
712624
713349
  if (slug5.length > MAX_WORKTREE_SLUG_LENGTH) {
712625
713350
  throw new Error(`Invalid worktree name: must be ${MAX_WORKTREE_SLUG_LENGTH} characters or fewer (got ${slug5.length})`);
@@ -712815,7 +713540,7 @@ async function copyWorktreeIncludeFiles(repoRoot, worktreePath) {
712815
713540
  const srcPath = join232(repoRoot, relativePath3);
712816
713541
  const destPath = join232(worktreePath, relativePath3);
712817
713542
  try {
712818
- await mkdir43(dirname85(destPath), { recursive: true });
713543
+ await mkdir43(dirname86(destPath), { recursive: true });
712819
713544
  await copyFile10(srcPath, destPath);
712820
713545
  copied.push(relativePath3);
712821
713546
  } catch (e) {
@@ -712832,7 +713557,7 @@ async function performPostCreationSetup(repoRoot, worktreePath) {
712832
713557
  const sourceSettingsLocal = join232(repoRoot, localSettingsRelativePath);
712833
713558
  try {
712834
713559
  const destSettingsLocal = join232(worktreePath, localSettingsRelativePath);
712835
- await mkdirRecursive(dirname85(destSettingsLocal));
713560
+ await mkdirRecursive(dirname86(destSettingsLocal));
712836
713561
  await copyFile10(sourceSettingsLocal, destSettingsLocal);
712837
713562
  logForDebugging(`Copied settings.local.json to worktree: ${destSettingsLocal}`);
712838
713563
  } catch (e) {
@@ -714379,7 +715104,7 @@ function computeFingerprint(messageText2, version3) {
714379
715104
  }
714380
715105
  function computeFingerprintFromMessages(messages) {
714381
715106
  const firstMessageText = extractFirstMessageText(messages);
714382
- return computeFingerprint(firstMessageText, "1.65.10");
715107
+ return computeFingerprint(firstMessageText, "1.65.12");
714383
715108
  }
714384
715109
  var FINGERPRINT_SALT = "59cf53e54c78";
714385
715110
  var init_fingerprint = () => {};
@@ -714774,7 +715499,9 @@ function getNonstreamingFallbackTimeoutMs(model, env4 = process.env, provider =
714774
715499
  const override = parseInt(env4.API_TIMEOUT_MS || "", 10);
714775
715500
  if (override)
714776
715501
  return override;
714777
- return isEnvTruthy(env4.UR_CODE_REMOTE) || isOllamaCloudRuntime(model, provider) ? 120000 : 300000;
715502
+ if (isEnvTruthy(env4.UR_CODE_REMOTE))
715503
+ return 120000;
715504
+ return provider === "ollama" ? getOllamaModelDefaultTimeoutMs(model) : 300000;
714778
715505
  }
714779
715506
  function shouldSkipOllamaNonStreamingFallback(error40, model, provider = getAPIProvider()) {
714780
715507
  return isOllamaCloudRuntime(model, provider) && error40 instanceof APIConnectionTimeoutError && error40.message === "Ollama stream timed out";
@@ -716232,6 +716959,7 @@ var init_ur2 = __esm(() => {
716232
716959
  init_utils3();
716233
716960
  init_vcr();
716234
716961
  init_client2();
716962
+ init_ollama();
716235
716963
  init_errors6();
716236
716964
  init_logging();
716237
716965
  init_promptCacheBreakDetection();
@@ -716275,7 +717003,7 @@ async function sideQuery(opts) {
716275
717003
  betas.push(STRUCTURED_OUTPUTS_BETA_HEADER);
716276
717004
  }
716277
717005
  const messageText2 = extractFirstUserMessageText(messages);
716278
- const fingerprint2 = computeFingerprint(messageText2, "1.65.10");
717006
+ const fingerprint2 = computeFingerprint(messageText2, "1.65.12");
716279
717007
  const attributionHeader = getAttributionHeader(fingerprint2);
716280
717008
  const systemBlocks = [
716281
717009
  attributionHeader ? { type: "text", text: attributionHeader } : null,
@@ -721062,7 +721790,7 @@ function buildSystemInitMessage(inputs) {
721062
721790
  slash_commands: inputs.commands.filter((c4) => c4.userInvocable !== false).map((c4) => c4.name),
721063
721791
  apiKeySource: getURHQApiKeyWithSource().source,
721064
721792
  betas: getSdkBetas(),
721065
- ur_version: "1.65.10",
721793
+ ur_version: "1.65.12",
721066
721794
  output_style: outputStyle2,
721067
721795
  agents: inputs.agents.map((agent2) => agent2.agentType),
721068
721796
  skills: inputs.skills.filter((s) => s.userInvocable !== false).map((skill2) => skill2.name),
@@ -722243,6 +722971,29 @@ var init_useNotifyAfterTimeout = __esm(() => {
722243
722971
  import_react196 = __toESM(require_react(), 1);
722244
722972
  });
722245
722973
 
722974
+ // src/components/permissions/AskUserQuestionPermissionRequest/prototypeSafeRecord.ts
722975
+ function createPrototypeSafeRecord() {
722976
+ return Object.create(null);
722977
+ }
722978
+ function clonePrototypeSafeRecord(source) {
722979
+ return Object.assign(Object.create(null), source);
722980
+ }
722981
+ function hasOwnRecordKey(record4, key) {
722982
+ return record4 !== null && record4 !== undefined && hasOwn2.call(record4, key);
722983
+ }
722984
+ function getOwnRecordValue(record4, key) {
722985
+ return hasOwnRecordKey(record4, key) ? record4[key] : undefined;
722986
+ }
722987
+ function setPrototypeSafeRecordValue(record4, key, value2) {
722988
+ const next = Object.assign(createPrototypeSafeRecord(), record4);
722989
+ next[key] = value2;
722990
+ return next;
722991
+ }
722992
+ var hasOwn2;
722993
+ var init_prototypeSafeRecord = __esm(() => {
722994
+ hasOwn2 = Object.prototype.hasOwnProperty;
722995
+ });
722996
+
722246
722997
  // src/components/permissions/AskUserQuestionPermissionRequest/QuestionNavigationBar.tsx
722247
722998
  function QuestionNavigationBar(t0) {
722248
722999
  const $2 = import_compiler_runtime262.c(39);
@@ -722350,7 +723101,7 @@ function QuestionNavigationBar(t0) {
722350
723101
  if ($2[22] !== answers || $2[23] !== currentQuestionIndex || $2[24] !== tabDisplayTexts) {
722351
723102
  t52 = (q_1, index_2) => {
722352
723103
  const isSelected = index_2 === currentQuestionIndex;
722353
- const isAnswered = q_1?.question && !!answers[q_1.question];
723104
+ const isAnswered = q_1?.question && !!getOwnRecordValue(answers, q_1.question);
722354
723105
  const checkbox = isAnswered ? figures_default.checkboxOn : figures_default.checkboxOff;
722355
723106
  const displayText = tabDisplayTexts[index_2] || q_1?.header || `Q${index_2 + 1}`;
722356
723107
  return /* @__PURE__ */ jsx_dev_runtime357.jsxDEV(ThemedBox_default, {
@@ -722472,6 +723223,7 @@ var init_QuestionNavigationBar = __esm(() => {
722472
723223
  init_stringWidth();
722473
723224
  init_ink2();
722474
723225
  init_format2();
723226
+ init_prototypeSafeRecord();
722475
723227
  import_compiler_runtime262 = __toESM(require_compiler_runtime(), 1);
722476
723228
  jsx_dev_runtime357 = __toESM(require_jsx_dev_runtime(), 1);
722477
723229
  });
@@ -722772,20 +723524,34 @@ function PreviewQuestionView({
722772
723524
  const editor = getExternalEditor();
722773
723525
  const editorName = editor ? toIDEDisplayName(editor) : null;
722774
723526
  const questionText = question.question;
722775
- const questionState = questionStates[questionText];
723527
+ const questionState = getOwnRecordValue(questionStates, questionText);
722776
723528
  const allOptions = question.options;
723529
+ const otherIndex = allOptions.length;
723530
+ const optionRowCount = allOptions.length + 1;
722777
723531
  const [focusedIndex, setFocusedIndex] = import_react198.useState(0);
722778
723532
  const prevQuestionText = import_react198.useRef(questionText);
722779
723533
  if (prevQuestionText.current !== questionText) {
722780
723534
  prevQuestionText.current = questionText;
722781
723535
  const selected = questionState?.selectedValue;
722782
- const idx = selected ? allOptions.findIndex((opt) => opt.label === selected) : -1;
723536
+ const idx = selected === PREVIEW_OTHER_VALUE ? otherIndex : selected ? allOptions.findIndex((opt) => opt.label === selected) : -1;
722783
723537
  setFocusedIndex(idx >= 0 ? idx : 0);
722784
723538
  }
722785
723539
  const focusedOption = allOptions[focusedIndex];
723540
+ const isOtherFocused = focusedIndex === otherIndex;
722786
723541
  const selectedValue = questionState?.selectedValue;
722787
723542
  const notesValue = questionState?.textInputValue || "";
723543
+ const otherInputValue = questionState?.otherInputValue || "";
722788
723544
  const handleSelectOption = import_react198.useCallback((index2) => {
723545
+ if (index2 === otherIndex) {
723546
+ setFocusedIndex(index2);
723547
+ onUpdateQuestionState(questionText, {
723548
+ selectedValue: PREVIEW_OTHER_VALUE
723549
+ }, false);
723550
+ onAnswer(questionText, PREVIEW_OTHER_VALUE, "", false);
723551
+ setIsInNotesInput(true);
723552
+ onTextInputFocus(true);
723553
+ return;
723554
+ }
722789
723555
  const option27 = allOptions[index2];
722790
723556
  if (!option27)
722791
723557
  return;
@@ -722794,7 +723560,7 @@ function PreviewQuestionView({
722794
723560
  selectedValue: option27.label
722795
723561
  }, false);
722796
723562
  onAnswer(questionText, option27.label);
722797
- }, [allOptions, questionText, onUpdateQuestionState, onAnswer]);
723563
+ }, [allOptions, otherIndex, questionText, onUpdateQuestionState, onAnswer, onTextInputFocus]);
722798
723564
  const handleNavigate = import_react198.useCallback((direction) => {
722799
723565
  if (isInNotesInput)
722800
723566
  return;
@@ -722804,18 +723570,18 @@ function PreviewQuestionView({
722804
723570
  } else if (direction === "up") {
722805
723571
  newIndex = focusedIndex > 0 ? focusedIndex - 1 : focusedIndex;
722806
723572
  } else {
722807
- newIndex = focusedIndex < allOptions.length - 1 ? focusedIndex + 1 : focusedIndex;
723573
+ newIndex = focusedIndex < optionRowCount - 1 ? focusedIndex + 1 : focusedIndex;
722808
723574
  }
722809
- if (newIndex >= 0 && newIndex < allOptions.length) {
723575
+ if (newIndex >= 0 && newIndex < optionRowCount) {
722810
723576
  setFocusedIndex(newIndex);
722811
723577
  }
722812
- }, [focusedIndex, allOptions.length, isInNotesInput]);
723578
+ }, [focusedIndex, optionRowCount, isInNotesInput]);
722813
723579
  useKeybinding("chat:externalEditor", async () => {
722814
- const currentValue = questionState?.textInputValue || "";
723580
+ const currentValue = isOtherFocused ? otherInputValue : notesValue;
722815
723581
  const result = await editPromptInEditor(currentValue);
722816
723582
  if (result.content !== null && result.content !== currentValue) {
722817
723583
  onUpdateQuestionState(questionText, {
722818
- textInputValue: result.content
723584
+ ...isOtherFocused ? { otherInputValue: result.content } : { textInputValue: result.content }
722819
723585
  }, false);
722820
723586
  }
722821
723587
  }, {
@@ -722832,10 +723598,17 @@ function PreviewQuestionView({
722832
723598
  const handleNotesExit = import_react198.useCallback(() => {
722833
723599
  setIsInNotesInput(false);
722834
723600
  onTextInputFocus(false);
722835
- if (selectedValue) {
723601
+ if (isOtherFocused) {
723602
+ const customAnswer = otherInputValue.trim();
723603
+ if (customAnswer) {
723604
+ onAnswer(questionText, PREVIEW_OTHER_VALUE, customAnswer);
723605
+ }
723606
+ return;
723607
+ }
723608
+ if (selectedValue && selectedValue !== PREVIEW_OTHER_VALUE) {
722836
723609
  onAnswer(questionText, selectedValue);
722837
723610
  }
722838
- }, [selectedValue, questionText, onAnswer, onTextInputFocus]);
723611
+ }, [isOtherFocused, otherInputValue, selectedValue, questionText, onAnswer, onTextInputFocus]);
722839
723612
  const handleDownFromPreview = import_react198.useCallback(() => {
722840
723613
  setIsFooterFocused(true);
722841
723614
  }, []);
@@ -722889,7 +723662,7 @@ function PreviewQuestionView({
722889
723662
  }
722890
723663
  } else if (e.key === "down" || e.ctrl && e.key === "n") {
722891
723664
  e.preventDefault();
722892
- if (focusedIndex === allOptions.length - 1) {
723665
+ if (focusedIndex === optionRowCount - 1) {
722893
723666
  handleDownFromPreview();
722894
723667
  } else {
722895
723668
  handleNavigate("down");
@@ -722899,6 +723672,11 @@ function PreviewQuestionView({
722899
723672
  handleSelectOption(focusedIndex);
722900
723673
  } else if (e.key === "n" && !e.ctrl && !e.meta) {
722901
723674
  e.preventDefault();
723675
+ if (isOtherFocused && selectedValue !== PREVIEW_OTHER_VALUE) {
723676
+ onUpdateQuestionState(questionText, {
723677
+ selectedValue: PREVIEW_OTHER_VALUE
723678
+ }, false);
723679
+ }
722902
723680
  setIsInNotesInput(true);
722903
723681
  onTextInputFocus(true);
722904
723682
  } else if (e.key === "escape") {
@@ -722907,12 +723685,13 @@ function PreviewQuestionView({
722907
723685
  } else if (e.key.length === 1 && e.key >= "1" && e.key <= "9") {
722908
723686
  e.preventDefault();
722909
723687
  const idx_0 = parseInt(e.key, 10) - 1;
722910
- if (idx_0 < allOptions.length) {
723688
+ if (idx_0 < optionRowCount) {
722911
723689
  handleNavigate(idx_0);
722912
723690
  }
722913
723691
  }
722914
- }, [isFooterFocused, footerIndex, isInPlanMode, isInNotesInput, focusedIndex, allOptions.length, handleUpFromFooter, handleDownFromPreview, handleNavigate, handleSelectOption, handleNotesExit, onRespondToUR, onFinishPlanInterview, onCancel, onTextInputFocus]);
722915
- const previewContent = focusedOption?.preview || null;
723692
+ }, [isFooterFocused, footerIndex, isInPlanMode, isInNotesInput, focusedIndex, optionRowCount, isOtherFocused, selectedValue, questionText, handleUpFromFooter, handleDownFromPreview, handleNavigate, handleSelectOption, handleNotesExit, onRespondToUR, onFinishPlanInterview, onCancel, onTextInputFocus, onUpdateQuestionState]);
723693
+ const previewContent = isOtherFocused ? "Enter a custom answer below." : focusedOption?.preview || null;
723694
+ const currentInputValue = isOtherFocused ? otherInputValue : notesValue;
722916
723695
  const LEFT_PANEL_WIDTH = 30;
722917
723696
  const GAP = 4;
722918
723697
  const {
@@ -722951,13 +723730,49 @@ function PreviewQuestionView({
722951
723730
  /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedBox_default, {
722952
723731
  flexDirection: "column",
722953
723732
  width: 30,
722954
- children: allOptions.map((option_0, index_0) => {
722955
- const isFocused = focusedIndex === index_0;
722956
- const isSelected = selectedValue === option_0.label;
722957
- return /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedBox_default, {
723733
+ children: [
723734
+ allOptions.map((option_0, index_0) => {
723735
+ const isFocused = focusedIndex === index_0;
723736
+ const isSelected = selectedValue === option_0.label;
723737
+ return /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedBox_default, {
723738
+ flexDirection: "row",
723739
+ children: [
723740
+ isFocused ? /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723741
+ color: "suggestion",
723742
+ children: figures_default.pointer
723743
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723744
+ children: " "
723745
+ }, undefined, false, undefined, this),
723746
+ /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723747
+ dimColor: true,
723748
+ children: [
723749
+ " ",
723750
+ index_0 + 1,
723751
+ "."
723752
+ ]
723753
+ }, undefined, true, undefined, this),
723754
+ /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723755
+ color: isSelected ? "success" : isFocused ? "suggestion" : undefined,
723756
+ bold: isFocused,
723757
+ children: [
723758
+ " ",
723759
+ option_0.label
723760
+ ]
723761
+ }, undefined, true, undefined, this),
723762
+ isSelected && /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723763
+ color: "success",
723764
+ children: [
723765
+ " ",
723766
+ figures_default.tick
723767
+ ]
723768
+ }, undefined, true, undefined, this)
723769
+ ]
723770
+ }, option_0.label, true, undefined, this);
723771
+ }),
723772
+ /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedBox_default, {
722958
723773
  flexDirection: "row",
722959
723774
  children: [
722960
- isFocused ? /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723775
+ isOtherFocused ? /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
722961
723776
  color: "suggestion",
722962
723777
  children: figures_default.pointer
722963
723778
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
@@ -722967,19 +723782,19 @@ function PreviewQuestionView({
722967
723782
  dimColor: true,
722968
723783
  children: [
722969
723784
  " ",
722970
- index_0 + 1,
723785
+ otherIndex + 1,
722971
723786
  "."
722972
723787
  ]
722973
723788
  }, undefined, true, undefined, this),
722974
723789
  /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
722975
- color: isSelected ? "success" : isFocused ? "suggestion" : undefined,
722976
- bold: isFocused,
723790
+ color: selectedValue === PREVIEW_OTHER_VALUE ? "success" : isOtherFocused ? "suggestion" : undefined,
723791
+ bold: isOtherFocused,
722977
723792
  children: [
722978
723793
  " ",
722979
- option_0.label
723794
+ "Other"
722980
723795
  ]
722981
723796
  }, undefined, true, undefined, this),
722982
- isSelected && /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723797
+ selectedValue === PREVIEW_OTHER_VALUE && /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
722983
723798
  color: "success",
722984
723799
  children: [
722985
723800
  " ",
@@ -722987,9 +723802,9 @@ function PreviewQuestionView({
722987
723802
  ]
722988
723803
  }, undefined, true, undefined, this)
722989
723804
  ]
722990
- }, option_0.label, true, undefined, this);
722991
- })
722992
- }, undefined, false, undefined, this),
723805
+ }, PREVIEW_OTHER_VALUE, true, undefined, this)
723806
+ ]
723807
+ }, undefined, true, undefined, this),
722993
723808
  /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedBox_default, {
722994
723809
  flexDirection: "column",
722995
723810
  flexGrow: 1,
@@ -723007,14 +723822,14 @@ function PreviewQuestionView({
723007
723822
  children: [
723008
723823
  /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723009
723824
  color: "suggestion",
723010
- children: "Notes:"
723825
+ children: isOtherFocused ? "Answer:" : "Notes:"
723011
723826
  }, undefined, false, undefined, this),
723012
723827
  isInNotesInput ? /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(TextInput, {
723013
- value: notesValue,
723014
- placeholder: "Add notes on this design\u2026",
723828
+ value: currentInputValue,
723829
+ placeholder: isOtherFocused ? "Type a custom answer\u2026" : "Add notes on this design\u2026",
723015
723830
  onChange: (value2) => {
723016
723831
  onUpdateQuestionState(questionText, {
723017
- textInputValue: value2
723832
+ ...isOtherFocused ? { otherInputValue: value2 } : { textInputValue: value2 }
723018
723833
  }, false);
723019
723834
  },
723020
723835
  onSubmit: handleNotesExit,
@@ -723027,7 +723842,7 @@ function PreviewQuestionView({
723027
723842
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(ThemedText, {
723028
723843
  dimColor: true,
723029
723844
  italic: true,
723030
- children: notesValue || "press n to add notes"
723845
+ children: currentInputValue || (isOtherFocused ? "press Enter to type a custom answer" : "press n to add notes")
723031
723846
  }, undefined, false, undefined, this)
723032
723847
  ]
723033
723848
  }, undefined, true, undefined, this)
@@ -723086,7 +723901,8 @@ function PreviewQuestionView({
723086
723901
  figures_default.arrowUp,
723087
723902
  "/",
723088
723903
  figures_default.arrowDown,
723089
- " to navigate \xB7 n to add notes",
723904
+ " to navigate \xB7 n to edit ",
723905
+ isOtherFocused ? "answer" : "notes",
723090
723906
  questions.length > 1 && /* @__PURE__ */ jsx_dev_runtime359.jsxDEV(jsx_dev_runtime359.Fragment, {
723091
723907
  children: " \xB7 Tab to switch questions"
723092
723908
  }, undefined, false, undefined, this),
@@ -723107,7 +723923,7 @@ function PreviewQuestionView({
723107
723923
  }, undefined, true, undefined, this)
723108
723924
  }, undefined, false, undefined, this);
723109
723925
  }
723110
- var import_react198, jsx_dev_runtime359;
723926
+ var import_react198, jsx_dev_runtime359, PREVIEW_OTHER_VALUE = "__other__";
723111
723927
  var init_PreviewQuestionView = __esm(() => {
723112
723928
  init_figures();
723113
723929
  init_useTerminalSize();
@@ -723120,6 +723936,7 @@ var init_PreviewQuestionView = __esm(() => {
723120
723936
  init_Divider();
723121
723937
  init_TextInput();
723122
723938
  init_PreviewBox();
723939
+ init_prototypeSafeRecord();
723123
723940
  init_QuestionNavigationBar();
723124
723941
  import_react198 = __toESM(require_react(), 1);
723125
723942
  jsx_dev_runtime359 = __toESM(require_jsx_dev_runtime(), 1);
@@ -723153,6 +723970,7 @@ function QuestionView({
723153
723970
  const [isFooterFocused, setIsFooterFocused] = import_react199.useState(false);
723154
723971
  const [footerIndex, setFooterIndex] = import_react199.useState(0);
723155
723972
  const [isOtherFocused, setIsOtherFocused] = import_react199.useState(false);
723973
+ const questionState = getOwnRecordValue(questionStates, question.question);
723156
723974
  const editorName = import_react199.useMemo(() => {
723157
723975
  const editor = getExternalEditor();
723158
723976
  return editor ? toIDEDisplayName(editor) : null;
@@ -723216,7 +724034,7 @@ function QuestionView({
723216
724034
  }
723217
724035
  };
723218
724036
  const placeholder = question.multiSelect ? "Type something" : "Type something.";
723219
- const textInputValue = questionStates[question.question]?.textInputValue ?? "";
724037
+ const textInputValue = questionState?.textInputValue ?? "";
723220
724038
  return [
723221
724039
  ...textOptions,
723222
724040
  {
@@ -723231,7 +724049,7 @@ function QuestionView({
723231
724049
  onOpenEditor: handleOpenEditor
723232
724050
  }
723233
724051
  ];
723234
- }, [question, questionStates, onUpdateQuestionState]);
724052
+ }, [question, questionState, onUpdateQuestionState]);
723235
724053
  const hasAnyPreview = !question.multiSelect && question.options.some((opt) => opt.preview);
723236
724054
  if (hasAnyPreview) {
723237
724055
  return /* @__PURE__ */ jsx_dev_runtime360.jsxDEV(PreviewQuestionView, {
@@ -723294,10 +724112,10 @@ function QuestionView({
723294
724112
  marginTop: 1,
723295
724113
  children: question.multiSelect ? /* @__PURE__ */ jsx_dev_runtime360.jsxDEV(SelectMulti, {
723296
724114
  options: options4,
723297
- defaultValue: questionStates[question.question]?.selectedValue,
724115
+ defaultValue: questionState?.selectedValue,
723298
724116
  onChange: (values2) => {
723299
724117
  onUpdateQuestionState(question.question, { selectedValue: values2 }, true);
723300
- const textInput = values2.includes("__other__") ? questionStates[question.question]?.textInputValue : undefined;
724118
+ const textInput = values2.includes("__other__") ? questionState?.textInputValue : undefined;
723301
724119
  const finalValues = values2.filter((v) => v !== "__other__").concat(textInput ? [textInput] : []);
723302
724120
  onAnswer(question.question, finalValues, undefined, false);
723303
724121
  },
@@ -723312,10 +724130,10 @@ function QuestionView({
723312
724130
  onRemoveImage
723313
724131
  }, question.question, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime360.jsxDEV(Select, {
723314
724132
  options: options4,
723315
- defaultValue: questionStates[question.question]?.selectedValue,
724133
+ defaultValue: questionState?.selectedValue,
723316
724134
  onChange: (value2) => {
723317
724135
  onUpdateQuestionState(question.question, { selectedValue: value2 }, false);
723318
- const textInput = value2 === "__other__" ? questionStates[question.question]?.textInputValue : undefined;
724136
+ const textInput = value2 === "__other__" ? questionState?.textInputValue : undefined;
723319
724137
  onAnswer(question.question, value2, textInput);
723320
724138
  },
723321
724139
  onFocus: handleFocus,
@@ -723419,6 +724237,7 @@ var init_QuestionView = __esm(() => {
723419
724237
  init_FilePathLink();
723420
724238
  init_QuestionNavigationBar();
723421
724239
  init_PreviewQuestionView();
724240
+ init_prototypeSafeRecord();
723422
724241
  import_react199 = __toESM(require_react(), 1);
723423
724242
  jsx_dev_runtime360 = __toESM(require_jsx_dev_runtime(), 1);
723424
724243
  });
@@ -723590,8 +724409,8 @@ function SubmitQuestionsView({
723590
724409
  Object.keys(answers).length > 0 && /* @__PURE__ */ jsx_dev_runtime362.jsxDEV(ThemedBox_default, {
723591
724410
  flexDirection: "column",
723592
724411
  marginBottom: 1,
723593
- children: questions.filter((q) => q?.question && answers[q.question]).map((q) => {
723594
- const answer = answers[q.question];
724412
+ children: questions.filter((q) => q?.question && getOwnRecordValue(answers, q.question)).map((q) => {
724413
+ const answer = getOwnRecordValue(answers, q.question);
723595
724414
  return /* @__PURE__ */ jsx_dev_runtime362.jsxDEV(ThemedBox_default, {
723596
724415
  flexDirection: "column",
723597
724416
  marginLeft: 1,
@@ -723648,12 +724467,13 @@ var init_SubmitQuestionsView = __esm(() => {
723648
724467
  init_CustomSelect();
723649
724468
  init_Divider();
723650
724469
  init_PermissionRuleExplanation();
724470
+ init_prototypeSafeRecord();
723651
724471
  init_QuestionNavigationBar();
723652
724472
  jsx_dev_runtime362 = __toESM(require_jsx_dev_runtime(), 1);
723653
724473
  });
723654
724474
 
723655
724475
  // src/components/permissions/AskUserQuestionPermissionRequest/use-multiple-choice-state.ts
723656
- function reducer2(state2, action3) {
724476
+ function multipleChoiceReducer(state2, action3) {
723657
724477
  switch (action3.type) {
723658
724478
  case "next-question":
723659
724479
  return {
@@ -723668,26 +724488,21 @@ function reducer2(state2, action3) {
723668
724488
  isInTextInput: false
723669
724489
  };
723670
724490
  case "update-question-state": {
723671
- const existing2 = state2.questionStates[action3.questionText];
724491
+ const existing2 = getOwnRecordValue(state2.questionStates, action3.questionText);
723672
724492
  const newState = {
723673
724493
  selectedValue: action3.updates.selectedValue ?? existing2?.selectedValue ?? (action3.isMultiSelect ? [] : undefined),
723674
- textInputValue: action3.updates.textInputValue ?? existing2?.textInputValue ?? ""
724494
+ textInputValue: action3.updates.textInputValue ?? existing2?.textInputValue ?? "",
724495
+ otherInputValue: action3.updates.otherInputValue ?? existing2?.otherInputValue ?? ""
723675
724496
  };
723676
724497
  return {
723677
724498
  ...state2,
723678
- questionStates: {
723679
- ...state2.questionStates,
723680
- [action3.questionText]: newState
723681
- }
724499
+ questionStates: setPrototypeSafeRecordValue(state2.questionStates, action3.questionText, newState)
723682
724500
  };
723683
724501
  }
723684
724502
  case "set-answer": {
723685
724503
  const newState = {
723686
724504
  ...state2,
723687
- answers: {
723688
- ...state2.answers,
723689
- [action3.questionText]: action3.answer
723690
- }
724505
+ answers: setPrototypeSafeRecordValue(state2.answers, action3.questionText, action3.answer)
723691
724506
  };
723692
724507
  if (action3.shouldAdvance) {
723693
724508
  return {
@@ -723705,8 +724520,16 @@ function reducer2(state2, action3) {
723705
724520
  };
723706
724521
  }
723707
724522
  }
724523
+ function createInitialMultipleChoiceState() {
724524
+ return {
724525
+ currentQuestionIndex: 0,
724526
+ answers: createPrototypeSafeRecord(),
724527
+ questionStates: createPrototypeSafeRecord(),
724528
+ isInTextInput: false
724529
+ };
724530
+ }
723708
724531
  function useMultipleChoiceState() {
723709
- const [state2, dispatch5] = import_react200.useReducer(reducer2, INITIAL_STATE2);
724532
+ const [state2, dispatch5] = import_react200.useReducer(multipleChoiceReducer, createInitialMultipleChoiceState());
723710
724533
  const nextQuestion = import_react200.useCallback(() => {
723711
724534
  dispatch5({ type: "next-question" });
723712
724535
  }, []);
@@ -723744,18 +724567,22 @@ function useMultipleChoiceState() {
723744
724567
  setTextInputMode
723745
724568
  };
723746
724569
  }
723747
- var import_react200, INITIAL_STATE2;
724570
+ var import_react200;
723748
724571
  var init_use_multiple_choice_state = __esm(() => {
724572
+ init_prototypeSafeRecord();
723749
724573
  import_react200 = __toESM(require_react(), 1);
723750
- INITIAL_STATE2 = {
723751
- currentQuestionIndex: 0,
723752
- answers: {},
723753
- questionStates: {},
723754
- isInTextInput: false
723755
- };
723756
724574
  });
723757
724575
 
723758
724576
  // src/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.tsx
724577
+ function resolveQuestionAnswer(label, textInput, hasImages) {
724578
+ if (Array.isArray(label))
724579
+ return label.join(", ");
724580
+ if (textInput)
724581
+ return hasImages ? `${textInput} (Image attached)` : textInput;
724582
+ if (label === "__other__")
724583
+ return hasImages ? "(Image attached)" : "";
724584
+ return label;
724585
+ }
723759
724586
  function AskUserQuestionPermissionRequest(props) {
723760
724587
  const settings = useSettings();
723761
724588
  if (settings.syntaxHighlightingDisabled) {
@@ -723818,7 +724645,7 @@ function AskUserQuestionPermissionRequestBody({
723818
724645
  }
723819
724646
  }
723820
724647
  const rightPanelHeight = maxPreviewBoxHeight + 2;
723821
- const leftPanelHeight = q.options.length + 2;
724648
+ const leftPanelHeight = q.options.length + 3;
723822
724649
  const sideByHeight = Math.max(leftPanelHeight, rightPanelHeight);
723823
724650
  maxHeight = Math.max(maxHeight, sideByHeight + 7);
723824
724651
  } else {
@@ -723827,7 +724654,7 @@ function AskUserQuestionPermissionRequestBody({
723827
724654
  }
723828
724655
  const globalContentHeight = Math.min(Math.max(maxHeight, MIN_CONTENT_HEIGHT), maxAllowedHeight);
723829
724656
  const globalContentWidth = Math.max(maxWidth, MIN_CONTENT_WIDTH);
723830
- const [pastedContentsByQuestion, setPastedContentsByQuestion] = import_react201.useState({});
724657
+ const [pastedContentsByQuestion, setPastedContentsByQuestion] = import_react201.useState(() => createPrototypeSafeRecord());
723831
724658
  const nextPasteIdRef = import_react201.useRef(0);
723832
724659
  const onImagePaste = import_react201.useCallback((questionText, base64Image, mediaType, filename, dimensions, _sourcePath) => {
723833
724660
  nextPasteIdRef.current += 1;
@@ -723842,22 +724669,19 @@ function AskUserQuestionPermissionRequestBody({
723842
724669
  };
723843
724670
  cacheImagePath(newContent);
723844
724671
  storeImage(newContent);
723845
- setPastedContentsByQuestion((prev) => ({
723846
- ...prev,
723847
- [questionText]: {
723848
- ...prev[questionText] ?? {},
723849
- [pasteId]: newContent
723850
- }
723851
- }));
724672
+ setPastedContentsByQuestion((prev) => {
724673
+ const previousQuestionContents = getOwnRecordValue(prev, questionText);
724674
+ const questionContents = previousQuestionContents ? clonePrototypeSafeRecord(previousQuestionContents) : Object.create(null);
724675
+ questionContents[pasteId] = newContent;
724676
+ return setPrototypeSafeRecordValue(prev, questionText, questionContents);
724677
+ });
723852
724678
  }, []);
723853
724679
  const onRemoveImage = import_react201.useCallback((questionText, id) => {
723854
724680
  setPastedContentsByQuestion((prev) => {
723855
- const questionContents = { ...prev[questionText] ?? {} };
724681
+ const previousQuestionContents = getOwnRecordValue(prev, questionText);
724682
+ const questionContents = previousQuestionContents ? clonePrototypeSafeRecord(previousQuestionContents) : Object.create(null);
723856
724683
  delete questionContents[id];
723857
- return {
723858
- ...prev,
723859
- [questionText]: questionContents
723860
- };
724684
+ return setPrototypeSafeRecordValue(prev, questionText, questionContents);
723861
724685
  });
723862
724686
  }, []);
723863
724687
  const allImageAttachments = import_react201.useMemo(() => Object.values(pastedContentsByQuestion).flatMap(Object.values).filter((c4) => c4.type === "image"), [pastedContentsByQuestion]);
@@ -723875,7 +724699,7 @@ function AskUserQuestionPermissionRequestBody({
723875
724699
  } = state2;
723876
724700
  const currentQuestion = currentQuestionIndex < (questions?.length || 0) ? questions?.[currentQuestionIndex] : null;
723877
724701
  const isInSubmitView = currentQuestionIndex === (questions?.length || 0);
723878
- const allQuestionsAnswered = questions?.every((q) => q?.question && !!answers[q.question]) ?? false;
724702
+ const allQuestionsAnswered = questions?.every((q) => q?.question && !!getOwnRecordValue(answers, q.question)) ?? false;
723879
724703
  const hideSubmitTab = questions.length === 1 && !questions[0]?.multiSelect;
723880
724704
  const handleCancel = import_react201.useCallback(() => {
723881
724705
  if (metadataSource) {
@@ -723892,7 +724716,7 @@ function AskUserQuestionPermissionRequestBody({
723892
724716
  }, [metadataSource, questions.length, isInPlanMode, onDone, onReject, toolUseConfirm]);
723893
724717
  const handleRespondToUR = import_react201.useCallback(async () => {
723894
724718
  const questionsWithAnswers = questions.map((q) => {
723895
- const answer = answers[q.question];
724719
+ const answer = getOwnRecordValue(answers, q.question);
723896
724720
  if (answer) {
723897
724721
  return `- "${q.question}"
723898
724722
  Answer: ${answer}`;
@@ -723922,7 +724746,7 @@ ${questionsWithAnswers}`;
723922
724746
  }, [allImageAttachments, answers, isInPlanMode, metadataSource, onDone, questions, toolUseConfirm]);
723923
724747
  const handleFinishPlanInterview = import_react201.useCallback(async () => {
723924
724748
  const questionsWithAnswers = questions.map((q) => {
723925
- const answer = answers[q.question];
724749
+ const answer = getOwnRecordValue(answers, q.question);
723926
724750
  if (answer) {
723927
724751
  return `- "${q.question}"
723928
724752
  Answer: ${answer}`;
@@ -723958,10 +724782,13 @@ ${questionsWithAnswers}`;
723958
724782
  interviewPhaseEnabled: isInPlanMode && isPlanModeInterviewPhaseEnabled()
723959
724783
  });
723960
724784
  }
723961
- const annotations = {};
724785
+ const annotations = createPrototypeSafeRecord();
723962
724786
  for (const q of questions) {
723963
- const answer = answersToSubmit[q.question];
723964
- const notes = questionStates[q.question]?.textInputValue;
724787
+ const answer = getOwnRecordValue(answersToSubmit, q.question);
724788
+ const questionState = getOwnRecordValue(questionStates, q.question);
724789
+ const selectedValue = questionState?.selectedValue;
724790
+ const selectedOther = selectedValue === "__other__" || Array.isArray(selectedValue) && selectedValue.includes("__other__");
724791
+ const notes = selectedOther ? undefined : questionState?.textInputValue;
723965
724792
  const selectedOption = answer ? q.options.find((opt) => opt.label === answer) : undefined;
723966
724793
  const preview6 = selectedOption?.preview;
723967
724794
  if (preview6 || notes?.trim()) {
@@ -723982,21 +724809,11 @@ ${questionsWithAnswers}`;
723982
724809
  }, [allImageAttachments, isInPlanMode, metadataSource, onDone, questionStates, questions, toolUseConfirm]);
723983
724810
  const handleQuestionAnswer = import_react201.useCallback((questionText, label, textInput, shouldAdvance = true) => {
723984
724811
  const isMultiSelect = Array.isArray(label);
723985
- let answer;
723986
- if (isMultiSelect) {
723987
- answer = label.join(", ");
723988
- } else if (textInput) {
723989
- const questionImages = Object.values(pastedContentsByQuestion[questionText] ?? {}).filter((c4) => c4.type === "image");
723990
- answer = questionImages.length > 0 ? `${textInput} (Image attached)` : textInput;
723991
- } else if (label === "__other__") {
723992
- const questionImages = Object.values(pastedContentsByQuestion[questionText] ?? {}).filter((c4) => c4.type === "image");
723993
- answer = questionImages.length > 0 ? "(Image attached)" : label;
723994
- } else {
723995
- answer = label;
723996
- }
724812
+ const hasImages = Object.values(getOwnRecordValue(pastedContentsByQuestion, questionText) ?? {}).some((content) => content.type === "image");
724813
+ const answer = resolveQuestionAnswer(label, textInput, hasImages);
723997
724814
  const isSingleQuestion = questions.length === 1;
723998
- if (!isMultiSelect && isSingleQuestion && shouldAdvance) {
723999
- const updatedAnswers = { ...answers, [questionText]: answer };
724815
+ if (!isMultiSelect && isSingleQuestion && shouldAdvance && answer) {
724816
+ const updatedAnswers = setPrototypeSafeRecordValue(answers, questionText, answer);
724000
724817
  submitAnswers(updatedAnswers).catch(logError2);
724001
724818
  return;
724002
724819
  }
@@ -724030,7 +724847,7 @@ ${questionsWithAnswers}`;
724030
724847
  isActive: !(isInTextInput && !isInSubmitView)
724031
724848
  });
724032
724849
  if (currentQuestion) {
724033
- const pastedContents = pastedContentsByQuestion[currentQuestion.question] ?? {};
724850
+ const pastedContents = getOwnRecordValue(pastedContentsByQuestion, currentQuestion.question) ?? Object.create(null);
724034
724851
  return /* @__PURE__ */ jsx_dev_runtime363.jsxDEV(PermissionDialog, {
724035
724852
  title: currentQuestion.question,
724036
724853
  onCancel: handleCancel,
@@ -724113,6 +724930,7 @@ var init_AskUserQuestionPermissionRequest = __esm(() => {
724113
724930
  init_planModeV2();
724114
724931
  init_plans();
724115
724932
  init_PermissionDialog();
724933
+ init_prototypeSafeRecord();
724116
724934
  init_QuestionView();
724117
724935
  init_SubmitQuestionsView();
724118
724936
  init_use_multiple_choice_state();
@@ -734923,7 +735741,7 @@ var init_useVoiceEnabled = __esm(() => {
734923
735741
  function getSemverPart(version3) {
734924
735742
  return `${import_semver13.major(version3, { loose: true })}.${import_semver13.minor(version3, { loose: true })}.${import_semver13.patch(version3, { loose: true })}`;
734925
735743
  }
734926
- function useUpdateNotification(updatedVersion, initialVersion = "1.65.10") {
735744
+ function useUpdateNotification(updatedVersion, initialVersion = "1.65.12") {
734927
735745
  const [lastNotifiedSemver, setLastNotifiedSemver] = import_react222.useState(() => getSemverPart(initialVersion));
734928
735746
  if (!updatedVersion) {
734929
735747
  return null;
@@ -734972,7 +735790,7 @@ function AutoUpdater({
734972
735790
  return;
734973
735791
  }
734974
735792
  if (false) {}
734975
- const currentVersion = "1.65.10";
735793
+ const currentVersion = "1.65.12";
734976
735794
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
734977
735795
  let latestVersion = await getLatestVersion(channel);
734978
735796
  const isDisabled = isAutoUpdaterDisabled();
@@ -735201,12 +736019,12 @@ function NativeAutoUpdater({
735201
736019
  logEvent("tengu_native_auto_updater_start", {});
735202
736020
  try {
735203
736021
  const maxVersion = await getMaxVersion();
735204
- if (maxVersion && gt("1.65.10", maxVersion)) {
736022
+ if (maxVersion && gt("1.65.12", maxVersion)) {
735205
736023
  const msg = await getMaxVersionMessage();
735206
736024
  setMaxVersionIssue(msg ?? "affects your version");
735207
736025
  }
735208
736026
  const result = await installLatest(channel);
735209
- const currentVersion = "1.65.10";
736027
+ const currentVersion = "1.65.12";
735210
736028
  const latencyMs = Date.now() - startTime;
735211
736029
  if (result.lockFailed) {
735212
736030
  logEvent("tengu_native_auto_updater_lock_contention", {
@@ -735343,17 +736161,17 @@ function PackageManagerAutoUpdater(t0) {
735343
736161
  const maxVersion = await getMaxVersion();
735344
736162
  if (maxVersion && latest && gt(latest, maxVersion)) {
735345
736163
  logForDebugging(`PackageManagerAutoUpdater: maxVersion ${maxVersion} is set, capping update from ${latest} to ${maxVersion}`);
735346
- if (gte("1.65.10", maxVersion)) {
735347
- logForDebugging(`PackageManagerAutoUpdater: current version ${"1.65.10"} is already at or above maxVersion ${maxVersion}, skipping update`);
736164
+ if (gte("1.65.12", maxVersion)) {
736165
+ logForDebugging(`PackageManagerAutoUpdater: current version ${"1.65.12"} is already at or above maxVersion ${maxVersion}, skipping update`);
735348
736166
  setUpdateAvailable(false);
735349
736167
  return;
735350
736168
  }
735351
736169
  latest = maxVersion;
735352
736170
  }
735353
- const hasUpdate = latest && !gte("1.65.10", latest) && !shouldSkipVersion(latest);
736171
+ const hasUpdate = latest && !gte("1.65.12", latest) && !shouldSkipVersion(latest);
735354
736172
  setUpdateAvailable(!!hasUpdate);
735355
736173
  if (hasUpdate) {
735356
- logForDebugging(`PackageManagerAutoUpdater: Update available ${"1.65.10"} -> ${latest}`);
736174
+ logForDebugging(`PackageManagerAutoUpdater: Update available ${"1.65.12"} -> ${latest}`);
735357
736175
  }
735358
736176
  };
735359
736177
  $2[0] = t1;
@@ -735387,7 +736205,7 @@ function PackageManagerAutoUpdater(t0) {
735387
736205
  wrap: "truncate",
735388
736206
  children: [
735389
736207
  "currentVersion: ",
735390
- "1.65.10"
736208
+ "1.65.12"
735391
736209
  ]
735392
736210
  }, undefined, true, undefined, this);
735393
736211
  $2[3] = verbose;
@@ -746107,7 +746925,7 @@ function buildStatusLineCommandInput(permissionMode, exceeds200kTokens, settings
746107
746925
  project_dir: getOriginalCwd(),
746108
746926
  added_dirs: addedDirs
746109
746927
  },
746110
- version: "1.65.10",
746928
+ version: "1.65.12",
746111
746929
  output_style: {
746112
746930
  name: outputStyleName
746113
746931
  },
@@ -746185,7 +747003,7 @@ function StatusLineInner({
746185
747003
  const taskValues = Object.values(tasks2);
746186
747004
  const taskRunningCount = countActiveBackgroundTasks(taskValues);
746187
747005
  const defaultStatusLineText = buildDefaultStatusBar({
746188
- version: "1.65.10",
747006
+ version: "1.65.12",
746189
747007
  providerLabel: providerRuntime.providerLabel,
746190
747008
  authMode: providerRuntime.authLabel,
746191
747009
  model: renderModelName(mainLoopModel) || providerRuntime.model || "",
@@ -747208,7 +748026,7 @@ var init_ghPrStatus = __esm(() => {
747208
748026
 
747209
748027
  // src/hooks/usePrStatus.ts
747210
748028
  function usePrStatus(isLoading, enabled = true) {
747211
- const [prStatus, setPrStatus] = import_react248.useState(INITIAL_STATE3);
748029
+ const [prStatus, setPrStatus] = import_react248.useState(INITIAL_STATE2);
747212
748030
  const timeoutRef = import_react248.useRef(null);
747213
748031
  const disabledRef = import_react248.useRef(false);
747214
748032
  const lastFetchRef = import_react248.useRef(0);
@@ -747272,13 +748090,13 @@ function usePrStatus(isLoading, enabled = true) {
747272
748090
  }, [isLoading, enabled]);
747273
748091
  return prStatus;
747274
748092
  }
747275
- var import_react248, POLL_INTERVAL_MS3 = 60000, SLOW_GH_THRESHOLD_MS = 4000, IDLE_STOP_MS, INITIAL_STATE3;
748093
+ var import_react248, POLL_INTERVAL_MS3 = 60000, SLOW_GH_THRESHOLD_MS = 4000, IDLE_STOP_MS, INITIAL_STATE2;
747276
748094
  var init_usePrStatus = __esm(() => {
747277
748095
  init_state();
747278
748096
  init_ghPrStatus();
747279
748097
  import_react248 = __toESM(require_react(), 1);
747280
748098
  IDLE_STOP_MS = 60 * 60000;
747281
- INITIAL_STATE3 = {
748099
+ INITIAL_STATE2 = {
747282
748100
  number: null,
747283
748101
  url: null,
747284
748102
  reviewState: null,
@@ -756719,7 +757537,7 @@ __export(exports_asciicast, {
756719
757537
  _resetRecordingStateForTesting: () => _resetRecordingStateForTesting
756720
757538
  });
756721
757539
  import { appendFile as appendFile7, rename as rename11 } from "fs/promises";
756722
- import { basename as basename66, dirname as dirname86, join as join238 } from "path";
757540
+ import { basename as basename66, dirname as dirname87, join as join238 } from "path";
756723
757541
  function getRecordFilePath() {
756724
757542
  if (recordingState.filePath !== null) {
756725
757543
  return recordingState.filePath;
@@ -756801,7 +757619,7 @@ function installAsciicastRecorder() {
756801
757619
  }
756802
757620
  });
756803
757621
  try {
756804
- getFsImplementation().mkdirSync(dirname86(filePath));
757622
+ getFsImplementation().mkdirSync(dirname87(filePath));
756805
757623
  } catch {}
756806
757624
  getFsImplementation().appendFileSync(filePath, header + `
756807
757625
  `, { mode: 384 });
@@ -756870,7 +757688,7 @@ var init_asciicast = __esm(() => {
756870
757688
  });
756871
757689
 
756872
757690
  // src/utils/sessionRestore.ts
756873
- import { dirname as dirname87 } from "path";
757691
+ import { dirname as dirname88 } from "path";
756874
757692
  function extractTodosFromTranscript(messages) {
756875
757693
  for (let i3 = messages.length - 1;i3 >= 0; i3--) {
756876
757694
  const msg = messages[i3];
@@ -756995,7 +757813,7 @@ async function processResumedConversation(result, opts, context6) {
756995
757813
  if (!opts.forkSession) {
756996
757814
  const sid = opts.sessionIdOverride ?? result.sessionId;
756997
757815
  if (sid) {
756998
- switchSession(asSessionId(sid), opts.transcriptPath ? dirname87(opts.transcriptPath) : null);
757816
+ switchSession(asSessionId(sid), opts.transcriptPath ? dirname88(opts.transcriptPath) : null);
756999
757817
  await renameRecordingForSession();
757000
757818
  await resetSessionFilePointer();
757001
757819
  restoreCostStateForSession(sid);
@@ -758365,7 +759183,7 @@ async function submitTranscriptShare(messages, trigger2, appearanceId) {
758365
759183
  } catch {}
758366
759184
  const data = {
758367
759185
  trigger: trigger2,
758368
- version: "1.65.10",
759186
+ version: "1.65.12",
758369
759187
  platform: process.platform,
758370
759188
  transcript,
758371
759189
  subagentTranscripts: Object.keys(subagentTranscripts).length > 0 ? subagentTranscripts : undefined,
@@ -766095,7 +766913,7 @@ var exports_REPL = {};
766095
766913
  __export(exports_REPL, {
766096
766914
  REPL: () => REPL
766097
766915
  });
766098
- import { dirname as dirname88, join as join241 } from "path";
766916
+ import { dirname as dirname89, join as join241 } from "path";
766099
766917
  import { tmpdir as tmpdir20 } from "os";
766100
766918
  import { writeFile as writeFile47 } from "fs/promises";
766101
766919
  import { randomUUID as randomUUID83 } from "crypto";
@@ -767035,7 +767853,7 @@ function REPL({
767035
767853
  const targetSessionCosts = getStoredSessionCosts(sessionId);
767036
767854
  saveCurrentSessionCosts();
767037
767855
  resetCostState();
767038
- switchSession(asSessionId(sessionId), log2.fullPath ? dirname88(log2.fullPath) : null);
767856
+ switchSession(asSessionId(sessionId), log2.fullPath ? dirname89(log2.fullPath) : null);
767039
767857
  const {
767040
767858
  renameRecordingForSession: renameRecordingForSession2
767041
767859
  } = await Promise.resolve().then(() => (init_asciicast(), exports_asciicast));
@@ -770730,7 +771548,7 @@ function WelcomeV2() {
770730
771548
  dimColor: true,
770731
771549
  children: [
770732
771550
  "v",
770733
- "1.65.10"
771551
+ "1.65.12"
770734
771552
  ]
770735
771553
  }, undefined, true, undefined, this)
770736
771554
  ]
@@ -771990,7 +772808,7 @@ function completeOnboarding() {
771990
772808
  saveGlobalConfig((current) => ({
771991
772809
  ...current,
771992
772810
  hasCompletedOnboarding: true,
771993
- lastOnboardingVersion: "1.65.10"
772811
+ lastOnboardingVersion: "1.65.12"
771994
772812
  }));
771995
772813
  }
771996
772814
  function showDialog(root2, renderer) {
@@ -773134,7 +773952,7 @@ var exports_ResumeConversation = {};
773134
773952
  __export(exports_ResumeConversation, {
773135
773953
  ResumeConversation: () => ResumeConversation
773136
773954
  });
773137
- import { dirname as dirname89 } from "path";
773955
+ import { dirname as dirname90 } from "path";
773138
773956
  function parsePrIdentifier(value2) {
773139
773957
  const directNumber = parseInt(value2, 10);
773140
773958
  if (!isNaN(directNumber) && directNumber > 0) {
@@ -773266,7 +774084,7 @@ function ResumeConversation({
773266
774084
  }
773267
774085
  if (false) {}
773268
774086
  if (result_3.sessionId && !forkSession) {
773269
- switchSession(asSessionId(result_3.sessionId), log_0.fullPath ? dirname89(log_0.fullPath) : null);
774087
+ switchSession(asSessionId(result_3.sessionId), log_0.fullPath ? dirname90(log_0.fullPath) : null);
773270
774088
  await renameRecordingForSession();
773271
774089
  await resetSessionFilePointer();
773272
774090
  restoreCostStateForSession(result_3.sessionId);
@@ -776985,7 +777803,7 @@ var init_createDirectConnectSession = __esm(() => {
776985
777803
  });
776986
777804
 
776987
777805
  // src/utils/errorLogSink.ts
776988
- import { dirname as dirname90, join as join242 } from "path";
777806
+ import { dirname as dirname91, join as join242 } from "path";
776989
777807
  function getErrorsPath() {
776990
777808
  return join242(CACHE_PATHS.errors(), DATE + ".jsonl");
776991
777809
  }
@@ -777006,7 +777824,7 @@ function createJsonlWriter(options4) {
777006
777824
  function getLogWriter(path24) {
777007
777825
  let writer = logWriters.get(path24);
777008
777826
  if (!writer) {
777009
- const dir = dirname90(path24);
777827
+ const dir = dirname91(path24);
777010
777828
  writer = createJsonlWriter({
777011
777829
  writeFn: (content) => {
777012
777830
  try {
@@ -777034,7 +777852,7 @@ function appendToLog(path24, message) {
777034
777852
  cwd: getFsImplementation().cwd(),
777035
777853
  userType: process.env.USER_TYPE,
777036
777854
  sessionId: getSessionId(),
777037
- version: "1.65.10"
777855
+ version: "1.65.12"
777038
777856
  };
777039
777857
  getLogWriter(path24).write(messageWithTimestamp);
777040
777858
  }
@@ -781198,8 +782016,8 @@ async function getEnvLessBridgeConfig() {
781198
782016
  }
781199
782017
  async function checkEnvLessBridgeMinVersion() {
781200
782018
  const cfg = await getEnvLessBridgeConfig();
781201
- if (cfg.min_version && lt("1.65.10", cfg.min_version)) {
781202
- return `Your version of UR (${"1.65.10"}) is too old for Remote Control.
782019
+ if (cfg.min_version && lt("1.65.12", cfg.min_version)) {
782020
+ return `Your version of UR (${"1.65.12"}) is too old for Remote Control.
781203
782021
  Version ${cfg.min_version} or higher is required. Run \`ur update\` to update.`;
781204
782022
  }
781205
782023
  return null;
@@ -781527,14 +782345,14 @@ __export(exports_bridgePointer, {
781527
782345
  BRIDGE_POINTER_TTL_MS: () => BRIDGE_POINTER_TTL_MS
781528
782346
  });
781529
782347
  import { mkdir as mkdir47, readFile as readFile57, stat as stat51, unlink as unlink27, writeFile as writeFile50 } from "fs/promises";
781530
- import { dirname as dirname91, join as join247 } from "path";
782348
+ import { dirname as dirname92, join as join247 } from "path";
781531
782349
  function getBridgePointerPath(dir) {
781532
782350
  return join247(getProjectsDir(), sanitizePath2(dir), "bridge-pointer.json");
781533
782351
  }
781534
782352
  async function writeBridgePointer(dir, pointer) {
781535
782353
  const path24 = getBridgePointerPath(dir);
781536
782354
  try {
781537
- await mkdir47(dirname91(path24), { recursive: true });
782355
+ await mkdir47(dirname92(path24), { recursive: true });
781538
782356
  await writeFile50(path24, jsonStringify(pointer), "utf8");
781539
782357
  logForDebugging(`[bridge:pointer] wrote ${path24}`);
781540
782358
  } catch (err2) {
@@ -781673,7 +782491,7 @@ async function initBridgeCore(params) {
781673
782491
  const rawApi = createBridgeApiClient({
781674
782492
  baseUrl,
781675
782493
  getAccessToken,
781676
- runnerVersion: "1.65.10",
782494
+ runnerVersion: "1.65.12",
781677
782495
  onDebug: logForDebugging,
781678
782496
  onAuth401,
781679
782497
  getTrustedDeviceToken
@@ -783538,7 +784356,7 @@ __export(exports_print, {
783538
784356
  canBatchWith: () => canBatchWith
783539
784357
  });
783540
784358
  import { readFile as readFile58, stat as stat52, writeFile as writeFile51 } from "fs/promises";
783541
- import { dirname as dirname92 } from "path";
784359
+ import { dirname as dirname93 } from "path";
783542
784360
  import { cwd as cwd2 } from "process";
783543
784361
  import { randomUUID as randomUUID89 } from "crypto";
783544
784362
  function trackReceivedMessageUuid(uuid3) {
@@ -785995,7 +786813,7 @@ async function loadInitialMessages(setAppState, options4) {
785995
786813
  if (false) {}
785996
786814
  if (!options4.forkSession) {
785997
786815
  if (result.sessionId) {
785998
- switchSession(asSessionId(result.sessionId), result.fullPath ? dirname92(result.fullPath) : null);
786816
+ switchSession(asSessionId(result.sessionId), result.fullPath ? dirname93(result.fullPath) : null);
785999
786817
  if (persistSession) {
786000
786818
  await resetSessionFilePointer();
786001
786819
  }
@@ -786093,7 +786911,7 @@ async function loadInitialMessages(setAppState, options4) {
786093
786911
  }
786094
786912
  if (false) {}
786095
786913
  if (!options4.forkSession && result.sessionId) {
786096
- switchSession(asSessionId(result.sessionId), result.fullPath ? dirname92(result.fullPath) : null);
786914
+ switchSession(asSessionId(result.sessionId), result.fullPath ? dirname93(result.fullPath) : null);
786097
786915
  if (persistSession) {
786098
786916
  await resetSessionFilePointer();
786099
786917
  }
@@ -791146,7 +791964,7 @@ function getAgUiCapabilities() {
791146
791964
  name: "UR-Nexus",
791147
791965
  type: "ur-nexus",
791148
791966
  description: "Provider-flexible, local-first autonomous engineering workflow agent.",
791149
- version: "1.65.10",
791967
+ version: "1.65.12",
791150
791968
  provider: "UR",
791151
791969
  documentationUrl: "https://github.com/Maitham16/UR/blob/master/docs/AG_UI.md"
791152
791970
  },
@@ -792286,7 +793104,7 @@ function createMCPServer(cwd4, debug2, verbose) {
792286
793104
  };
792287
793105
  const server2 = new Server({
792288
793106
  name: "ur-nexus",
792289
- version: "1.65.10"
793107
+ version: "1.65.12"
792290
793108
  }, {
792291
793109
  capabilities: {
792292
793110
  tools: {}
@@ -793444,7 +794262,7 @@ function thrownResponse(error40) {
793444
794262
  }
793445
794263
  async function createUrMcp2026Runtime(options4) {
793446
794264
  const server2 = createMCPServer(options4.cwd, options4.debug === true, options4.verbose === true);
793447
- const client2 = new Client({ name: "ur-mcp-2026-adapter", version: "1.65.10" }, { capabilities: {} });
794265
+ const client2 = new Client({ name: "ur-mcp-2026-adapter", version: "1.65.12" }, { capabilities: {} });
793448
794266
  const [clientTransport, serverTransport] = createLinkedTransportPair();
793449
794267
  try {
793450
794268
  await server2.connect(serverTransport);
@@ -793455,7 +794273,7 @@ async function createUrMcp2026Runtime(options4) {
793455
794273
  }
793456
794274
  const runtime2 = new Mcp2026Runtime({
793457
794275
  cwd: options4.cwd,
793458
- version: "1.65.10",
794276
+ version: "1.65.12",
793459
794277
  backend: {
793460
794278
  listTools: async () => {
793461
794279
  const listed = await client2.listTools();
@@ -794418,7 +795236,7 @@ __export(exports_plugins, {
794418
795236
  VALID_UPDATE_SCOPES: () => VALID_UPDATE_SCOPES,
794419
795237
  VALID_INSTALLABLE_SCOPES: () => VALID_INSTALLABLE_SCOPES
794420
795238
  });
794421
- import { basename as basename69, dirname as dirname94, join as join251, resolve as resolve76 } from "path";
795239
+ import { basename as basename69, dirname as dirname95, join as join251, resolve as resolve76 } from "path";
794422
795240
  function handleMarketplaceError(error40, action3) {
794423
795241
  logError2(error40);
794424
795242
  cliError(`${figures_default.cross} Failed to ${action3}: ${errorMessage2(error40)}`);
@@ -794471,9 +795289,9 @@ async function pluginValidateHandler(manifestPath6, options4) {
794471
795289
  printValidationResult(result);
794472
795290
  let contentResults = [];
794473
795291
  if (result.fileType === "plugin") {
794474
- const manifestDir = dirname94(result.filePath);
795292
+ const manifestDir = dirname95(result.filePath);
794475
795293
  if (basename69(manifestDir) === ".ur-plugin") {
794476
- contentResults = await validatePluginContents(dirname94(manifestDir));
795294
+ contentResults = await validatePluginContents(dirname95(manifestDir));
794477
795295
  for (const r of contentResults) {
794478
795296
  console.log(`Validating ${r.fileType}: ${r.filePath}
794479
795297
  `);
@@ -795588,7 +796406,7 @@ async function update() {
795588
796406
  logEvent("tengu_update_check", {});
795589
796407
  const diagnostic2 = await getDoctorDiagnostic();
795590
796408
  const result = await checkUpgradeStatus({
795591
- currentVersion: "1.65.10",
796409
+ currentVersion: "1.65.12",
795592
796410
  packageName: UR_AGENT_PACKAGE_NAME,
795593
796411
  installationType: diagnostic2.installationType,
795594
796412
  latestVersion: () => getLatestNpmPackageVersion(UR_AGENT_PACKAGE_NAME)
@@ -796904,7 +797722,7 @@ ${customInstructions}` : customInstructions;
796904
797722
  }
796905
797723
  }
796906
797724
  logForDiagnosticsNoPII("info", "started", {
796907
- version: "1.65.10",
797725
+ version: "1.65.12",
796908
797726
  is_native_binary: isInBundledMode()
796909
797727
  });
796910
797728
  registerCleanup(async () => {
@@ -797690,7 +798508,7 @@ Usage: ur --remote "your task description"`, () => gracefulShutdown(1));
797690
798508
  pendingHookMessages
797691
798509
  }, renderAndRun);
797692
798510
  }
797693
- }).version("1.65.10 (UR-Nexus)", "-v, --version", "Output the version number");
798511
+ }).version("1.65.12 (UR-Nexus)", "-v, --version", "Output the version number");
797694
798512
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
797695
798513
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
797696
798514
  if (canUserConfigureAdvisor()) {
@@ -798749,7 +799567,7 @@ if (false) {}
798749
799567
  async function main2() {
798750
799568
  const args = process.argv.slice(2);
798751
799569
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
798752
- console.log(`${"1.65.10"} (UR-Nexus)`);
799570
+ console.log(`${"1.65.12"} (UR-Nexus)`);
798753
799571
  return;
798754
799572
  }
798755
799573
  if (args[0] === "a2a" && args[1] === "serve" && !args.includes("--help") && !args.includes("-h")) {