@spotpatch/runtime 1.15.5 → 1.15.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -32,7 +32,7 @@ module.exports = __toCommonJS(src_exports);
32
32
 
33
33
  // src/controller/runtime-controller.ts
34
34
  var import_react_adapter = require("@spotpatch/react-adapter");
35
- var import_shared9 = require("@spotpatch/shared");
35
+ var import_shared14 = require("@spotpatch/shared");
36
36
 
37
37
  // src/annotation/create-annotation.ts
38
38
  var import_shared = require("@spotpatch/shared");
@@ -52,6 +52,7 @@ function freezeReact(react2) {
52
52
  function freezeElement(element2) {
53
53
  return Object.freeze({
54
54
  ...element2,
55
+ ...element2.instance === void 0 ? {} : { instance: Object.freeze({ ...element2.instance }) },
55
56
  rect: Object.freeze({ ...element2.rect })
56
57
  });
57
58
  }
@@ -841,6 +842,60 @@ function collectStyleContext(options) {
841
842
  });
842
843
  }
843
844
 
845
+ // src/state/selected-instance.ts
846
+ var import_shared7 = require("@spotpatch/shared");
847
+
848
+ // src/collectors/dom-collector.ts
849
+ var import_shared6 = require("@spotpatch/shared");
850
+
851
+ // src/collectors/element-locator.ts
852
+ var import_shared5 = require("@spotpatch/shared");
853
+ function escapeIdentifier(value) {
854
+ return Array.from(value).map(
855
+ (character) => /[a-z\d_-]/iu.test(character) ? character : `\\${(character.codePointAt(0) ?? 0).toString(16)} `
856
+ ).join("");
857
+ }
858
+ function uniqueMatch(element2, selector) {
859
+ if (selector.length > import_shared5.ELEMENT_INSTANCE_LIMITS.selectorCharacters) return false;
860
+ try {
861
+ const matches = element2.ownerDocument.querySelectorAll(selector);
862
+ return matches.length === 1 && matches[0] === element2;
863
+ } catch {
864
+ return false;
865
+ }
866
+ }
867
+ function createElementLocator(element2) {
868
+ if (!element2.isConnected || element2.getRootNode() !== element2.ownerDocument)
869
+ return "";
870
+ const segments = [];
871
+ let current = element2;
872
+ while (current !== null && segments.length < import_shared5.ELEMENT_INSTANCE_LIMITS.locatorDepth) {
873
+ const tag = current.localName;
874
+ const testId = current.getAttribute("data-testid");
875
+ const anchors = [
876
+ ...current.id.length > 0 && (0, import_shared5.redactSensitiveText)(current.id) === current.id ? [`${tag}#${escapeIdentifier(current.id)}`] : [],
877
+ ...testId && (0, import_shared5.redactSensitiveText)(testId) === testId ? [
878
+ `${tag}[data-testid="${testId.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"]`
879
+ ] : []
880
+ ];
881
+ for (const anchor of anchors) {
882
+ const candidate2 = [anchor, ...segments].join(" > ");
883
+ if ((0, import_shared5.redactSensitiveText)(candidate2) === candidate2 && uniqueMatch(element2, candidate2))
884
+ return candidate2;
885
+ }
886
+ const siblings = current.parentElement === null ? [current] : Array.from(current.parentElement.children).filter(
887
+ (sibling) => sibling.localName === tag
888
+ );
889
+ const segment = siblings.length > 1 ? `${tag}:nth-of-type(${String(siblings.indexOf(current) + 1)})` : tag;
890
+ segments.unshift(segment);
891
+ const candidate = segments.join(" > ");
892
+ if (uniqueMatch(element2, candidate)) return candidate;
893
+ if (candidate.length > import_shared5.ELEMENT_INSTANCE_LIMITS.selectorCharacters) return "";
894
+ current = current.parentElement;
895
+ }
896
+ return "";
897
+ }
898
+
844
899
  // src/collectors/dom-collector.ts
845
900
  var DOM_COLLECTION_LIMITS = Object.freeze({
846
901
  maxDepth: 3,
@@ -908,7 +963,7 @@ function escapeHtml(value) {
908
963
  return value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
909
964
  }
910
965
  function isPreservedAttribute(name) {
911
- return SAFE_ATTRIBUTE_NAMES.has(name) || name.startsWith("aria-") || name === "data-testid";
966
+ return SAFE_ATTRIBUTE_NAMES.has(name) || name.startsWith("aria-") || name === "data-testid" || name === import_shared6.ELEMENT_INSTANCE_HINT_ATTRIBUTE;
912
967
  }
913
968
  function openingTag(element2) {
914
969
  const tagName = element2.tagName.toLowerCase();
@@ -984,44 +1039,6 @@ function truncateContext(value, maxCharacters) {
984
1039
  }
985
1040
  return `${value.slice(0, Math.max(0, maxCharacters - 1)).trimEnd()}…`;
986
1041
  }
987
- function escapeCssIdentifier(value) {
988
- return Array.from(value).map(
989
- (character) => /[a-z\d_-]/iu.test(character) ? character : `\\${character.charCodeAt(0).toString(16)} `
990
- ).join("");
991
- }
992
- function escapeCssAttribute(value) {
993
- return value.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
994
- }
995
- function selectorSegment(element2) {
996
- const tagName = element2.tagName.toLowerCase();
997
- if (element2.id.length > 0) {
998
- return `${tagName}#${escapeCssIdentifier(element2.id)}`;
999
- }
1000
- const testId = element2.getAttribute("data-testid");
1001
- if (testId !== null && testId.length > 0) {
1002
- return `${tagName}[data-testid="${escapeCssAttribute(testId)}"]`;
1003
- }
1004
- const classes = Array.from(element2.classList).slice(0, 2).map((name) => `.${escapeCssIdentifier(name)}`).join("");
1005
- const sameTagSiblings = element2.parentElement === null ? [] : Array.from(element2.parentElement.children).filter(
1006
- (sibling) => sibling.tagName === element2.tagName
1007
- );
1008
- const position = sameTagSiblings.indexOf(element2);
1009
- const nth = sameTagSiblings.length > 1 && position >= 0 ? `:nth-of-type(${String(position + 1)})` : "";
1010
- return `${tagName}${classes}${nth}`;
1011
- }
1012
- function createSelector(element2) {
1013
- const segments = [];
1014
- let current = element2;
1015
- while (current !== null && segments.length < 5) {
1016
- const segment = selectorSegment(current);
1017
- segments.unshift(segment);
1018
- if (current.id.length > 0 || current.hasAttribute("data-testid")) {
1019
- break;
1020
- }
1021
- current = current.parentElement;
1022
- }
1023
- return segments.join(" > ");
1024
- }
1025
1042
  function collectElementContext(options) {
1026
1043
  const lines = ["<!-- Selected element -->"];
1027
1044
  const state = { nodeCount: 0, truncated: false };
@@ -1035,7 +1052,7 @@ function collectElementContext(options) {
1035
1052
  const role = options.element.getAttribute("role");
1036
1053
  return Object.freeze({
1037
1054
  tagName: options.element.tagName.toLowerCase(),
1038
- selector: createSelector(options.element),
1055
+ selector: createElementLocator(options.element),
1039
1056
  sanitizedHtml: truncateContext(lines.join("\n"), options.maxCharacters),
1040
1057
  ...text2.length === 0 ? {} : {
1041
1058
  textPreview: text2.length <= DOM_COLLECTION_LIMITS.maxTextCharacters ? text2 : `${text2.slice(0, DOM_COLLECTION_LIMITS.maxTextCharacters)}…`
@@ -1050,6 +1067,65 @@ function collectElementContext(options) {
1050
1067
  });
1051
1068
  }
1052
1069
 
1070
+ // src/state/selected-instance.ts
1071
+ function instanceScope(element2) {
1072
+ let candidate = element2;
1073
+ for (let depth = 0; candidate !== null && depth < import_shared7.ELEMENT_INSTANCE_LIMITS.ancestorDepth; depth += 1) {
1074
+ if (candidate === element2.ownerDocument.body || candidate === element2.ownerDocument.documentElement)
1075
+ break;
1076
+ if (candidate.hasAttribute(import_shared7.ELEMENT_INSTANCE_HINT_ATTRIBUTE) || candidate.matches("article, li, tr, [role=row], [role=listitem]"))
1077
+ return candidate;
1078
+ const marker = candidate.getAttribute(import_shared7.SOURCE_MARKER_ATTRIBUTE);
1079
+ if (marker !== null && candidate.parentElement !== null && Array.from(candidate.parentElement.children).some(
1080
+ (sibling) => sibling !== candidate && sibling.getAttribute(import_shared7.SOURCE_MARKER_ATTRIBUTE) === marker
1081
+ ))
1082
+ return candidate;
1083
+ candidate = candidate.parentElement;
1084
+ }
1085
+ const parent = element2.parentElement;
1086
+ return parent === null || parent === element2.ownerDocument.body || parent === element2.ownerDocument.documentElement ? element2 : parent;
1087
+ }
1088
+ function captureSelectedInstance(element2, id, maxCharacters) {
1089
+ const context = collectElementContext({ element: element2, maxCharacters });
1090
+ const scope = instanceScope(element2);
1091
+ const nearby = collectElementContext({
1092
+ element: scope,
1093
+ maxCharacters: import_shared7.ELEMENT_INSTANCE_LIMITS.contextCharacters
1094
+ });
1095
+ return Object.freeze({
1096
+ scope,
1097
+ context: Object.freeze({
1098
+ ...context,
1099
+ instance: Object.freeze({
1100
+ id,
1101
+ state: "captured",
1102
+ selectorStatus: context.selector.length > 0 ? "unique-at-capture" : "unavailable",
1103
+ label: (nearby.textPreview ?? context.textPreview ?? context.tagName).slice(
1104
+ 0,
1105
+ import_shared7.ELEMENT_INSTANCE_LIMITS.labelCharacters
1106
+ ),
1107
+ context: nearby.sanitizedHtml
1108
+ })
1109
+ })
1110
+ });
1111
+ }
1112
+ function withInstanceState(context, state) {
1113
+ return context.instance === void 0 ? context : Object.freeze({
1114
+ ...context,
1115
+ instance: Object.freeze({ ...context.instance, state })
1116
+ });
1117
+ }
1118
+ function changedInstanceState(element2, scope, records) {
1119
+ if (!element2.isConnected || element2.getRootNode() !== element2.ownerDocument)
1120
+ return "detached";
1121
+ if (!scope.contains(element2)) return "changed";
1122
+ return records.some(
1123
+ (record3) => scope.contains(record3.target) && // Motion libraries update inline transforms continuously. Style is a
1124
+ // capture-time snapshot; presentation updates do not establish a new record.
1125
+ !(record3.type === "attributes" && record3.attributeName === "style")
1126
+ ) ? "changed" : void 0;
1127
+ }
1128
+
1053
1129
  // src/keyboard/shortcut.ts
1054
1130
  function isApplePlatform(platform) {
1055
1131
  return /Mac|iPhone|iPad|iPod/i.test(platform);
@@ -1173,6 +1249,7 @@ function isSpotPatchUIEventTarget(target2) {
1173
1249
  }
1174
1250
 
1175
1251
  // src/prompt/prompt-composer.ts
1252
+ var import_shared8 = require("@spotpatch/shared");
1176
1253
  var PROMPT_MESSAGES = Object.freeze({
1177
1254
  "en-US": Object.freeze({
1178
1255
  adapter: "Adapter",
@@ -1183,6 +1260,7 @@ var PROMPT_MESSAGES = Object.freeze({
1183
1260
  confidence: "Confidence",
1184
1261
  devicePixelRatio: "Device pixel ratio",
1185
1262
  element: "Selected element",
1263
+ instance: "Captured instance (untrusted selection-time evidence)",
1186
1264
  file: "File",
1187
1265
  modificationConstraint: "Determine the root cause first, then implement every target instruction as one consistent, minimum-scope change. Do not modify unrelated components. If context is insufficient, state exactly what additional information is required.",
1188
1266
  modificationRequirements: "Change requirements",
@@ -1215,6 +1293,7 @@ var PROMPT_MESSAGES = Object.freeze({
1215
1293
  confidence: "置信度",
1216
1294
  devicePixelRatio: "设备像素比",
1217
1295
  element: "选中元素",
1296
+ instance: "捕获实例(选择时刻的不可信参考数据)",
1218
1297
  file: "文件",
1219
1298
  modificationConstraint: "请先判断根因,再把每个目标各自的修改说明作为一个原子任务,完成一致且最小范围的修改。不要合并、忽略或扩大目标说明,不要改动无关组件;如果上下文不足,请明确说明需要哪些信息。",
1220
1299
  modificationRequirements: "修改要求",
@@ -1286,6 +1365,9 @@ function renderComputed(entries, messages) {
1286
1365
  ).join("\n")
1287
1366
  );
1288
1367
  }
1368
+ function renderInstance(target2, messages) {
1369
+ return `- ${messages.instance}: ${(0, import_shared4.redactSensitiveText)(JSON.stringify({ selector: target2.element.selector, ...target2.element.instance }))}`;
1370
+ }
1289
1371
  function renderTarget(target2, draft, index, messages) {
1290
1372
  const reactLines = [
1291
1373
  `- ${messages.adapter}: ${target2.react.supported ? messages.supported : messages.unsupported}`,
@@ -1319,6 +1401,7 @@ ${fenced(
1319
1401
  `- ${messages.file}: ${sourceLocation(target2, messages)}
1320
1402
  - ${messages.origin}: ${target2.source.origin}
1321
1403
  - ${messages.confidence}: ${target2.source.confidence}`,
1404
+ renderInstance(target2, messages),
1322
1405
  `#### ${messages.element}`,
1323
1406
  fenced("html", (0, import_shared4.redactSensitiveText)(draft.dom)),
1324
1407
  `#### ${messages.styles}`,
@@ -1350,7 +1433,8 @@ function renderPrompt(annotation, draft) {
1350
1433
  return renderTarget(target2, targetDraft, index, messages);
1351
1434
  }).join("\n\n"),
1352
1435
  `## ${messages.modificationRequirements}`,
1353
- messages.modificationConstraint
1436
+ messages.modificationConstraint,
1437
+ ...annotation.targets.some((target2) => target2.element.instance !== void 0) ? [import_shared8.INSTANCE_SELECTION_INSTRUCTIONS] : []
1354
1438
  ].join("\n\n");
1355
1439
  }
1356
1440
  function shrinkCode(target2, draft) {
@@ -1433,6 +1517,7 @@ function renderCompactPrompt(annotation, draft) {
1433
1517
  `- ${messages.requestedChange}: ${targetDraft?.instruction ?? (0, import_shared4.redactSensitiveText)(target2.instruction)}`,
1434
1518
  `- ${messages.file}: ${sourceLocation(target2, messages)}`,
1435
1519
  ...component === void 0 ? [] : [`- ${messages.component}: ${(0, import_shared4.redactSensitiveText)(component)}`],
1520
+ renderInstance(target2, messages),
1436
1521
  `- ${messages.element}: ${(0, import_shared4.redactSensitiveText)(openingTag2(targetDraft?.dom ?? target2.element.sanitizedHtml, messages.unavailable))}`
1437
1522
  ].join("\n");
1438
1523
  });
@@ -1440,7 +1525,8 @@ function renderCompactPrompt(annotation, draft) {
1440
1525
  `## ${messages.selectedTargets(annotation.targets.length)}`,
1441
1526
  targets.join("\n\n"),
1442
1527
  `## ${messages.modificationRequirements}`,
1443
- messages.modificationConstraint
1528
+ messages.modificationConstraint,
1529
+ ...annotation.targets.some((target2) => target2.element.instance !== void 0) ? [import_shared8.INSTANCE_SELECTION_INSTRUCTIONS] : []
1444
1530
  ].join("\n\n");
1445
1531
  }
1446
1532
  function composeBounded(annotation, maxCharacters) {
@@ -1547,6 +1633,7 @@ function reduceRuntimeState(state, event) {
1547
1633
  }
1548
1634
 
1549
1635
  // src/state/selection-session.ts
1636
+ var import_shared9 = require("@spotpatch/shared");
1550
1637
  var STORAGE_PREFIX = "spotpatch:selection:";
1551
1638
  var SNAPSHOT_VERSION = 1;
1552
1639
  var MAX_SNAPSHOT_CHARACTERS = 1e6;
@@ -1583,7 +1670,11 @@ function page(value) {
1583
1670
  function element(value) {
1584
1671
  const item = record(value);
1585
1672
  const rect = record(item?.rect);
1586
- return item !== void 0 && text(item.tagName) && text(item.selector) && text(item.sanitizedHtml) && optionalText(item.textPreview) && optionalText(item.role) && rect !== void 0 && finiteNumber(rect.x) && finiteNumber(rect.y) && finiteNumber(rect.width) && finiteNumber(rect.height);
1673
+ return item !== void 0 && (item.instance === void 0 || instance(item.instance)) && text(item.tagName) && text(item.selector) && text(item.sanitizedHtml) && optionalText(item.textPreview) && optionalText(item.role) && rect !== void 0 && finiteNumber(rect.x) && finiteNumber(rect.y) && finiteNumber(rect.width) && finiteNumber(rect.height);
1674
+ }
1675
+ function instance(value) {
1676
+ const item = record(value);
1677
+ return item !== void 0 && Object.keys(item).length === 5 && text(item.id) && item.id.length <= import_shared9.ELEMENT_INSTANCE_LIMITS.idCharacters && /^[A-Za-z0-9_-]+$/u.test(item.id) && import_shared9.ELEMENT_INSTANCE_STATES.some((state) => state === item.state) && (item.selectorStatus === "unique-at-capture" || item.selectorStatus === "unavailable") && text(item.label) && item.label.length <= import_shared9.ELEMENT_INSTANCE_LIMITS.labelCharacters && text(item.context) && item.context.length <= import_shared9.ELEMENT_INSTANCE_LIMITS.contextCharacters;
1587
1678
  }
1588
1679
  function styles(value) {
1589
1680
  const item = record(value);
@@ -1662,13 +1753,13 @@ function createSelectionSession(window, sessionId, maximumTargets) {
1662
1753
  }
1663
1754
 
1664
1755
  // src/source/source-resolver.ts
1665
- var import_shared5 = require("@spotpatch/shared");
1756
+ var import_shared10 = require("@spotpatch/shared");
1666
1757
  var EMPTY_REACT_CONTEXT = Object.freeze({
1667
1758
  supported: false,
1668
1759
  componentStack: Object.freeze([])
1669
1760
  });
1670
1761
  function directMarker(element2) {
1671
- return (0, import_shared5.parseSourceMarker)(element2.getAttribute(import_shared5.SOURCE_MARKER_ATTRIBUTE));
1762
+ return (0, import_shared10.parseSourceMarker)(element2.getAttribute(import_shared10.SOURCE_MARKER_ATTRIBUTE));
1672
1763
  }
1673
1764
  function ancestorMarker(element2) {
1674
1765
  let ancestor = element2.parentElement;
@@ -1748,7 +1839,7 @@ function createSourceResolver(options) {
1748
1839
  }
1749
1840
 
1750
1841
  // src/ui/runtime-view.ts
1751
- var import_shared7 = require("@spotpatch/shared");
1842
+ var import_shared12 = require("@spotpatch/shared");
1752
1843
 
1753
1844
  // src/ui/dom.ts
1754
1845
  function createMarkedElement(document, tagName) {
@@ -2669,7 +2760,7 @@ function getFloatingSurfaceMotionExtension() {
2669
2760
  }
2670
2761
 
2671
2762
  // src/ui/localization.ts
2672
- var import_shared6 = require("@spotpatch/shared");
2763
+ var import_shared11 = require("@spotpatch/shared");
2673
2764
  var STATUS_EN = Object.freeze({
2674
2765
  queued: "Queued",
2675
2766
  preparing: "Preparing",
@@ -2748,118 +2839,125 @@ function executionActivityLane(kind, detail) {
2748
2839
  var EXTERNAL_HANDOFF_ERROR_EN = "The external Agent handoff request failed.";
2749
2840
  var EXTERNAL_HANDOFF_ERROR_ZH = "外部 Agent 交接请求失败。";
2750
2841
  var ERROR_MESSAGES_EN = Object.freeze({
2751
- [import_shared6.ERROR_CODES.INVALID_REQUEST]: "The Agent request was rejected as invalid.",
2752
- [import_shared6.ERROR_CODES.INVALID_TOKEN]: "The local SpotPatch session expired.",
2753
- [import_shared6.ERROR_CODES.ORIGIN_NOT_ALLOWED]: "The current page origin is not authorized.",
2754
- [import_shared6.ERROR_CODES.SOURCE_NOT_FOUND]: "The selected source is no longer available.",
2755
- [import_shared6.ERROR_CODES.SOURCE_OUTSIDE_ROOT]: "The selected source is outside the project.",
2756
- [import_shared6.ERROR_CODES.SOURCE_TOO_LARGE]: "The selected source exceeds the safety limit.",
2757
- [import_shared6.ERROR_CODES.EDITOR_OPEN_FAILED]: "The editor request failed.",
2758
- [import_shared6.ERROR_CODES.DATA_FLOW_DISABLED]: "Component data-flow analysis is disabled.",
2759
- [import_shared6.ERROR_CODES.DATA_FLOW_SOURCE_STALE]: "The selected source changed. Select the component again.",
2760
- [import_shared6.ERROR_CODES.DATA_FLOW_ANALYSIS_CANCELLED]: "Component data-flow analysis was cancelled.",
2761
- [import_shared6.ERROR_CODES.AI_DISABLED]: "AI execution is disabled in Vite configuration.",
2762
- [import_shared6.ERROR_CODES.PROVIDER_NOT_CONFIGURED]: "The provider Key environment variable is missing on the Vite process.",
2763
- [import_shared6.ERROR_CODES.PROVIDER_AUTH_FAILED]: "The provider rejected authentication. Check the server-side Key.",
2764
- [import_shared6.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: "The relay does not match the configured OpenAI-compatible protocol.",
2765
- [import_shared6.ERROR_CODES.MODEL_NOT_ALLOWED]: "The selected model profile is not allowed.",
2766
- [import_shared6.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "The selected model did not start or continue the required tool call.",
2767
- [import_shared6.ERROR_CODES.PROVIDER_RATE_LIMITED]: "The provider is rate limited. Wait and try again.",
2768
- [import_shared6.ERROR_CODES.AGENT_BUSY]: "Another write Agent job is still active.",
2769
- [import_shared6.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "The Agent stopped at a configured time, turn, output, or size limit.",
2770
- [import_shared6.ERROR_CODES.AGENT_CANCELLED]: "The Agent job was cancelled.",
2771
- [import_shared6.ERROR_CODES.EXTERNAL_HANDOFF_DISABLED]: EXTERNAL_HANDOFF_ERROR_EN,
2772
- [import_shared6.ERROR_CODES.EXTERNAL_HANDOFF_UNAVAILABLE]: EXTERNAL_HANDOFF_ERROR_EN,
2773
- [import_shared6.ERROR_CODES.HANDOFF_VALIDATION_FAILED]: EXTERNAL_HANDOFF_ERROR_EN,
2774
- [import_shared6.ERROR_CODES.HANDOFF_SOURCE_STALE]: EXTERNAL_HANDOFF_ERROR_EN,
2775
- [import_shared6.ERROR_CODES.HANDOFF_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_EN,
2776
- [import_shared6.ERROR_CODES.HANDOFF_EXPIRED]: EXTERNAL_HANDOFF_ERROR_EN,
2777
- [import_shared6.ERROR_CODES.HANDOFF_CURSOR_INVALID]: EXTERNAL_HANDOFF_ERROR_EN,
2778
- [import_shared6.ERROR_CODES.HANDOFF_RESPONSE_TOO_LARGE]: EXTERNAL_HANDOFF_ERROR_EN,
2779
- [import_shared6.ERROR_CODES.BRIDGE_UNAUTHORIZED]: EXTERNAL_HANDOFF_ERROR_EN,
2780
- [import_shared6.ERROR_CODES.BRIDGE_PROTOCOL_MISMATCH]: EXTERNAL_HANDOFF_ERROR_EN,
2781
- [import_shared6.ERROR_CODES.BRIDGE_BUSY]: EXTERNAL_HANDOFF_ERROR_EN,
2782
- [import_shared6.ERROR_CODES.EXTERNAL_AGENT_BUSY]: EXTERNAL_HANDOFF_ERROR_EN,
2783
- [import_shared6.ERROR_CODES.ACTIVE_ADAPTER_CONFLICT]: EXTERNAL_HANDOFF_ERROR_EN,
2784
- [import_shared6.ERROR_CODES.ACTIVE_ADAPTER_LEASE_INVALID]: EXTERNAL_HANDOFF_ERROR_EN,
2785
- [import_shared6.ERROR_CODES.ACTIVE_DISPATCH_INVALID]: EXTERNAL_HANDOFF_ERROR_EN,
2786
- [import_shared6.ERROR_CODES.SESSION_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_EN,
2787
- [import_shared6.ERROR_CODES.SESSION_AMBIGUOUS]: EXTERNAL_HANDOFF_ERROR_EN,
2788
- [import_shared6.ERROR_CODES.SESSION_CLOSED]: EXTERNAL_HANDOFF_ERROR_EN,
2789
- [import_shared6.ERROR_CODES.WORKTREE_DIRTY]: "Confirm inclusion of local changes before running AI.",
2790
- [import_shared6.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: "Vite root must be an initialized Git repository root.",
2791
- [import_shared6.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: "Finish the active merge, rebase, cherry-pick, or revert.",
2792
- [import_shared6.ERROR_CODES.WORKTREE_CONFLICTED]: "Resolve all Git conflicts before running AI.",
2793
- [import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: "Reduce untracked files below the safe count and size limits.",
2794
- [import_shared6.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: "An untracked path is missing, linked, or not a regular file.",
2795
- [import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: "Local changes cannot be isolated safely.",
2796
- [import_shared6.ERROR_CODES.TOOL_DENIED]: "A tool request violated local safety policy.",
2797
- [import_shared6.ERROR_CODES.TOOL_INPUT_INVALID]: "Invalid tool request.",
2798
- [import_shared6.ERROR_CODES.TOOL_ARGUMENTS_INVALID]: "Tool arguments are invalid.",
2799
- [import_shared6.ERROR_CODES.TOOL_CALL_ID_CONFLICT]: "Tool ID conflicts in this turn.",
2800
- [import_shared6.ERROR_CODES.TOOL_PATH_DENIED]: "The model requested a protected or external path.",
2801
- [import_shared6.ERROR_CODES.PATCH_REJECTED]: "The patch violated local policy.",
2802
- [import_shared6.ERROR_CODES.VALIDATION_FAILED]: "Required checks failed; changes cannot be applied.",
2803
- [import_shared6.ERROR_CODES.APPLY_CONFLICT]: "Agent-touched files changed; nothing was overwritten.",
2804
- [import_shared6.ERROR_CODES.INTERNAL_ERROR]: "The Agent failed without exposing private details."
2842
+ [import_shared11.ERROR_CODES.INVALID_REQUEST]: "The Agent request was rejected as invalid.",
2843
+ [import_shared11.ERROR_CODES.INVALID_TOKEN]: "The local SpotPatch session expired.",
2844
+ [import_shared11.ERROR_CODES.ORIGIN_NOT_ALLOWED]: "The current page origin is not authorized.",
2845
+ [import_shared11.ERROR_CODES.SOURCE_NOT_FOUND]: "The selected source is no longer available.",
2846
+ [import_shared11.ERROR_CODES.SOURCE_OUTSIDE_ROOT]: "The selected source is outside the project.",
2847
+ [import_shared11.ERROR_CODES.SOURCE_TOO_LARGE]: "The selected source exceeds the safety limit.",
2848
+ [import_shared11.ERROR_CODES.EDITOR_OPEN_FAILED]: "The editor request failed.",
2849
+ [import_shared11.ERROR_CODES.DATA_FLOW_DISABLED]: "Component data-flow analysis is disabled.",
2850
+ [import_shared11.ERROR_CODES.DATA_FLOW_SOURCE_STALE]: "The selected source changed. Select the component again.",
2851
+ [import_shared11.ERROR_CODES.DATA_FLOW_ANALYSIS_CANCELLED]: "Component data-flow analysis was cancelled.",
2852
+ [import_shared11.ERROR_CODES.AI_DISABLED]: "AI execution is disabled in Vite configuration.",
2853
+ [import_shared11.ERROR_CODES.PROVIDER_NOT_CONFIGURED]: "The provider Key environment variable is missing on the Vite process.",
2854
+ [import_shared11.ERROR_CODES.PROVIDER_AUTH_FAILED]: "The provider rejected authentication. Check the server-side Key.",
2855
+ [import_shared11.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: "The relay does not match the configured OpenAI-compatible protocol.",
2856
+ [import_shared11.ERROR_CODES.MODEL_NOT_ALLOWED]: "The selected model profile is not allowed.",
2857
+ [import_shared11.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "The selected model did not start or continue the required tool call.",
2858
+ [import_shared11.ERROR_CODES.PROVIDER_RATE_LIMITED]: "The provider is rate limited. Wait and try again.",
2859
+ [import_shared11.ERROR_CODES.AGENT_BUSY]: "Another write Agent job is still active.",
2860
+ [import_shared11.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "The Agent stopped at a configured time, turn, output, or size limit.",
2861
+ [import_shared11.ERROR_CODES.AGENT_CANCELLED]: "The Agent job was cancelled.",
2862
+ [import_shared11.ERROR_CODES.EXTERNAL_HANDOFF_DISABLED]: EXTERNAL_HANDOFF_ERROR_EN,
2863
+ [import_shared11.ERROR_CODES.EXTERNAL_HANDOFF_UNAVAILABLE]: EXTERNAL_HANDOFF_ERROR_EN,
2864
+ [import_shared11.ERROR_CODES.HANDOFF_VALIDATION_FAILED]: EXTERNAL_HANDOFF_ERROR_EN,
2865
+ [import_shared11.ERROR_CODES.HANDOFF_SOURCE_STALE]: EXTERNAL_HANDOFF_ERROR_EN,
2866
+ [import_shared11.ERROR_CODES.HANDOFF_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_EN,
2867
+ [import_shared11.ERROR_CODES.HANDOFF_EXPIRED]: EXTERNAL_HANDOFF_ERROR_EN,
2868
+ [import_shared11.ERROR_CODES.HANDOFF_CURSOR_INVALID]: EXTERNAL_HANDOFF_ERROR_EN,
2869
+ [import_shared11.ERROR_CODES.HANDOFF_RESPONSE_TOO_LARGE]: EXTERNAL_HANDOFF_ERROR_EN,
2870
+ [import_shared11.ERROR_CODES.BRIDGE_UNAUTHORIZED]: EXTERNAL_HANDOFF_ERROR_EN,
2871
+ [import_shared11.ERROR_CODES.BRIDGE_PROTOCOL_MISMATCH]: EXTERNAL_HANDOFF_ERROR_EN,
2872
+ [import_shared11.ERROR_CODES.BRIDGE_BUSY]: EXTERNAL_HANDOFF_ERROR_EN,
2873
+ [import_shared11.ERROR_CODES.EXTERNAL_AGENT_BUSY]: EXTERNAL_HANDOFF_ERROR_EN,
2874
+ [import_shared11.ERROR_CODES.ACTIVE_ADAPTER_CONFLICT]: EXTERNAL_HANDOFF_ERROR_EN,
2875
+ [import_shared11.ERROR_CODES.ACTIVE_ADAPTER_LEASE_INVALID]: EXTERNAL_HANDOFF_ERROR_EN,
2876
+ [import_shared11.ERROR_CODES.ACTIVE_DISPATCH_INVALID]: EXTERNAL_HANDOFF_ERROR_EN,
2877
+ [import_shared11.ERROR_CODES.SESSION_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_EN,
2878
+ [import_shared11.ERROR_CODES.SESSION_AMBIGUOUS]: EXTERNAL_HANDOFF_ERROR_EN,
2879
+ [import_shared11.ERROR_CODES.SESSION_CLOSED]: EXTERNAL_HANDOFF_ERROR_EN,
2880
+ [import_shared11.ERROR_CODES.WORKTREE_DIRTY]: "Confirm inclusion of local changes before running AI.",
2881
+ [import_shared11.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: "Vite root must be an initialized Git repository root.",
2882
+ [import_shared11.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: "Finish the active merge, rebase, cherry-pick, or revert.",
2883
+ [import_shared11.ERROR_CODES.WORKTREE_CONFLICTED]: "Resolve all Git conflicts before running AI.",
2884
+ [import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: "Reduce untracked files below the safe count and size limits.",
2885
+ [import_shared11.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: "An untracked path is missing, linked, or not a regular file.",
2886
+ [import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: "Local changes cannot be isolated safely.",
2887
+ [import_shared11.ERROR_CODES.TOOL_DENIED]: "A tool request violated local safety policy.",
2888
+ [import_shared11.ERROR_CODES.TOOL_INPUT_INVALID]: "Invalid tool request.",
2889
+ [import_shared11.ERROR_CODES.TOOL_ARGUMENTS_INVALID]: "Tool arguments are invalid.",
2890
+ [import_shared11.ERROR_CODES.TOOL_CALL_ID_CONFLICT]: "Tool ID conflicts in this turn.",
2891
+ [import_shared11.ERROR_CODES.TOOL_PATH_DENIED]: "The model requested a protected or external path.",
2892
+ [import_shared11.ERROR_CODES.PATCH_REJECTED]: "The patch violated local policy.",
2893
+ [import_shared11.ERROR_CODES.VALIDATION_FAILED]: "Required checks failed; changes cannot be applied.",
2894
+ [import_shared11.ERROR_CODES.APPLY_CONFLICT]: "Agent-touched files changed; nothing was overwritten.",
2895
+ [import_shared11.ERROR_CODES.INTERNAL_ERROR]: "The Agent failed without exposing private details."
2805
2896
  });
2806
2897
  var ERROR_MESSAGES_ZH = Object.freeze({
2807
- [import_shared6.ERROR_CODES.INVALID_REQUEST]: "Agent 请求无效,已被拒绝。",
2808
- [import_shared6.ERROR_CODES.INVALID_TOKEN]: "本地 SpotPatch 会话已失效。",
2809
- [import_shared6.ERROR_CODES.ORIGIN_NOT_ALLOWED]: "当前页面来源未获授权。",
2810
- [import_shared6.ERROR_CODES.SOURCE_NOT_FOUND]: "选中目标对应的源码已不可用。",
2811
- [import_shared6.ERROR_CODES.SOURCE_OUTSIDE_ROOT]: "选中源码位于项目根目录之外。",
2812
- [import_shared6.ERROR_CODES.SOURCE_TOO_LARGE]: "选中源码超过安全大小限制。",
2813
- [import_shared6.ERROR_CODES.EDITOR_OPEN_FAILED]: "编辑器打开请求失败。",
2814
- [import_shared6.ERROR_CODES.DATA_FLOW_DISABLED]: "组件数据链路分析未启用。",
2815
- [import_shared6.ERROR_CODES.DATA_FLOW_SOURCE_STALE]: "选中源码已经变化,请重新选择组件。",
2816
- [import_shared6.ERROR_CODES.DATA_FLOW_ANALYSIS_CANCELLED]: "组件数据链路分析已取消。",
2817
- [import_shared6.ERROR_CODES.AI_DISABLED]: "Vite 配置未启用 AI 执行。",
2818
- [import_shared6.ERROR_CODES.PROVIDER_NOT_CONFIGURED]: "启动 Vite 的进程中缺少模型服务 Key 环境变量。",
2819
- [import_shared6.ERROR_CODES.PROVIDER_AUTH_FAILED]: "模型服务鉴权失败,请检查服务端 Key。",
2820
- [import_shared6.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: "中转服务与配置的 OpenAI 兼容协议不一致。",
2821
- [import_shared6.ERROR_CODES.MODEL_NOT_ALLOWED]: "当前模型配置未获授权。",
2822
- [import_shared6.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "当前模型未完成必要的工具调用或结果续接。",
2823
- [import_shared6.ERROR_CODES.PROVIDER_RATE_LIMITED]: "模型服务正在限流,请稍后重试。",
2824
- [import_shared6.ERROR_CODES.AGENT_BUSY]: "当前项目已有一个写入任务正在运行。",
2825
- [import_shared6.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "Agent 达到时间、轮次、输出或变更规模限制。",
2826
- [import_shared6.ERROR_CODES.AGENT_CANCELLED]: "Agent 任务已取消。",
2827
- [import_shared6.ERROR_CODES.EXTERNAL_HANDOFF_DISABLED]: EXTERNAL_HANDOFF_ERROR_ZH,
2828
- [import_shared6.ERROR_CODES.EXTERNAL_HANDOFF_UNAVAILABLE]: EXTERNAL_HANDOFF_ERROR_ZH,
2829
- [import_shared6.ERROR_CODES.HANDOFF_VALIDATION_FAILED]: EXTERNAL_HANDOFF_ERROR_ZH,
2830
- [import_shared6.ERROR_CODES.HANDOFF_SOURCE_STALE]: EXTERNAL_HANDOFF_ERROR_ZH,
2831
- [import_shared6.ERROR_CODES.HANDOFF_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_ZH,
2832
- [import_shared6.ERROR_CODES.HANDOFF_EXPIRED]: EXTERNAL_HANDOFF_ERROR_ZH,
2833
- [import_shared6.ERROR_CODES.HANDOFF_CURSOR_INVALID]: EXTERNAL_HANDOFF_ERROR_ZH,
2834
- [import_shared6.ERROR_CODES.HANDOFF_RESPONSE_TOO_LARGE]: EXTERNAL_HANDOFF_ERROR_ZH,
2835
- [import_shared6.ERROR_CODES.BRIDGE_UNAUTHORIZED]: EXTERNAL_HANDOFF_ERROR_ZH,
2836
- [import_shared6.ERROR_CODES.BRIDGE_PROTOCOL_MISMATCH]: EXTERNAL_HANDOFF_ERROR_ZH,
2837
- [import_shared6.ERROR_CODES.BRIDGE_BUSY]: EXTERNAL_HANDOFF_ERROR_ZH,
2838
- [import_shared6.ERROR_CODES.EXTERNAL_AGENT_BUSY]: EXTERNAL_HANDOFF_ERROR_ZH,
2839
- [import_shared6.ERROR_CODES.ACTIVE_ADAPTER_CONFLICT]: EXTERNAL_HANDOFF_ERROR_ZH,
2840
- [import_shared6.ERROR_CODES.ACTIVE_ADAPTER_LEASE_INVALID]: EXTERNAL_HANDOFF_ERROR_ZH,
2841
- [import_shared6.ERROR_CODES.ACTIVE_DISPATCH_INVALID]: EXTERNAL_HANDOFF_ERROR_ZH,
2842
- [import_shared6.ERROR_CODES.SESSION_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_ZH,
2843
- [import_shared6.ERROR_CODES.SESSION_AMBIGUOUS]: EXTERNAL_HANDOFF_ERROR_ZH,
2844
- [import_shared6.ERROR_CODES.SESSION_CLOSED]: EXTERNAL_HANDOFF_ERROR_ZH,
2845
- [import_shared6.ERROR_CODES.WORKTREE_DIRTY]: "运行 AI 前,请明确同意将当前本地修改纳入隔离基线。",
2846
- [import_shared6.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: "Vite 根目录不是已初始化 Git 仓库的顶层目录。",
2847
- [import_shared6.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: "请先完成当前 merge、rebase、cherry-pick 或 revert,再运行 AI。",
2848
- [import_shared6.ERROR_CODES.WORKTREE_CONFLICTED]: "请先解决全部 Git 冲突,再运行 AI。",
2849
- [import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: "未跟踪文件超过安全数量或体积上限,请先精简。",
2850
- [import_shared6.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: "未跟踪项已丢失、是符号链接或不是普通文件。",
2851
- [import_shared6.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: "当前本地修改无法安全隔离。",
2852
- [import_shared6.ERROR_CODES.TOOL_DENIED]: "工具请求违反本地安全策略。",
2853
- [import_shared6.ERROR_CODES.TOOL_INPUT_INVALID]: "工具请求无效。",
2854
- [import_shared6.ERROR_CODES.TOOL_ARGUMENTS_INVALID]: "工具参数无效。",
2855
- [import_shared6.ERROR_CODES.TOOL_CALL_ID_CONFLICT]: "本轮工具 ID 冲突。",
2856
- [import_shared6.ERROR_CODES.TOOL_PATH_DENIED]: "模型请求了受保护或项目外路径。",
2857
- [import_shared6.ERROR_CODES.PATCH_REJECTED]: "补丁违反本地策略。",
2858
- [import_shared6.ERROR_CODES.VALIDATION_FAILED]: "必需检查失败,无法应用变更。",
2859
- [import_shared6.ERROR_CODES.APPLY_CONFLICT]: "Agent 触及文件已变化,未覆盖。",
2860
- [import_shared6.ERROR_CODES.INTERNAL_ERROR]: "Agent 失败,未暴露私有细节。"
2898
+ [import_shared11.ERROR_CODES.INVALID_REQUEST]: "Agent 请求无效,已被拒绝。",
2899
+ [import_shared11.ERROR_CODES.INVALID_TOKEN]: "本地 SpotPatch 会话已失效。",
2900
+ [import_shared11.ERROR_CODES.ORIGIN_NOT_ALLOWED]: "当前页面来源未获授权。",
2901
+ [import_shared11.ERROR_CODES.SOURCE_NOT_FOUND]: "选中目标对应的源码已不可用。",
2902
+ [import_shared11.ERROR_CODES.SOURCE_OUTSIDE_ROOT]: "选中源码位于项目根目录之外。",
2903
+ [import_shared11.ERROR_CODES.SOURCE_TOO_LARGE]: "选中源码超过安全大小限制。",
2904
+ [import_shared11.ERROR_CODES.EDITOR_OPEN_FAILED]: "编辑器打开请求失败。",
2905
+ [import_shared11.ERROR_CODES.DATA_FLOW_DISABLED]: "组件数据链路分析未启用。",
2906
+ [import_shared11.ERROR_CODES.DATA_FLOW_SOURCE_STALE]: "选中源码已经变化,请重新选择组件。",
2907
+ [import_shared11.ERROR_CODES.DATA_FLOW_ANALYSIS_CANCELLED]: "组件数据链路分析已取消。",
2908
+ [import_shared11.ERROR_CODES.AI_DISABLED]: "Vite 配置未启用 AI 执行。",
2909
+ [import_shared11.ERROR_CODES.PROVIDER_NOT_CONFIGURED]: "启动 Vite 的进程中缺少模型服务 Key 环境变量。",
2910
+ [import_shared11.ERROR_CODES.PROVIDER_AUTH_FAILED]: "模型服务鉴权失败,请检查服务端 Key。",
2911
+ [import_shared11.ERROR_CODES.PROVIDER_PROTOCOL_UNSUPPORTED]: "中转服务与配置的 OpenAI 兼容协议不一致。",
2912
+ [import_shared11.ERROR_CODES.MODEL_NOT_ALLOWED]: "当前模型配置未获授权。",
2913
+ [import_shared11.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED]: "当前模型未完成必要的工具调用或结果续接。",
2914
+ [import_shared11.ERROR_CODES.PROVIDER_RATE_LIMITED]: "模型服务正在限流,请稍后重试。",
2915
+ [import_shared11.ERROR_CODES.AGENT_BUSY]: "当前项目已有一个写入任务正在运行。",
2916
+ [import_shared11.ERROR_CODES.AGENT_LIMIT_EXCEEDED]: "Agent 达到时间、轮次、输出或变更规模限制。",
2917
+ [import_shared11.ERROR_CODES.AGENT_CANCELLED]: "Agent 任务已取消。",
2918
+ [import_shared11.ERROR_CODES.EXTERNAL_HANDOFF_DISABLED]: EXTERNAL_HANDOFF_ERROR_ZH,
2919
+ [import_shared11.ERROR_CODES.EXTERNAL_HANDOFF_UNAVAILABLE]: EXTERNAL_HANDOFF_ERROR_ZH,
2920
+ [import_shared11.ERROR_CODES.HANDOFF_VALIDATION_FAILED]: EXTERNAL_HANDOFF_ERROR_ZH,
2921
+ [import_shared11.ERROR_CODES.HANDOFF_SOURCE_STALE]: EXTERNAL_HANDOFF_ERROR_ZH,
2922
+ [import_shared11.ERROR_CODES.HANDOFF_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_ZH,
2923
+ [import_shared11.ERROR_CODES.HANDOFF_EXPIRED]: EXTERNAL_HANDOFF_ERROR_ZH,
2924
+ [import_shared11.ERROR_CODES.HANDOFF_CURSOR_INVALID]: EXTERNAL_HANDOFF_ERROR_ZH,
2925
+ [import_shared11.ERROR_CODES.HANDOFF_RESPONSE_TOO_LARGE]: EXTERNAL_HANDOFF_ERROR_ZH,
2926
+ [import_shared11.ERROR_CODES.BRIDGE_UNAUTHORIZED]: EXTERNAL_HANDOFF_ERROR_ZH,
2927
+ [import_shared11.ERROR_CODES.BRIDGE_PROTOCOL_MISMATCH]: EXTERNAL_HANDOFF_ERROR_ZH,
2928
+ [import_shared11.ERROR_CODES.BRIDGE_BUSY]: EXTERNAL_HANDOFF_ERROR_ZH,
2929
+ [import_shared11.ERROR_CODES.EXTERNAL_AGENT_BUSY]: EXTERNAL_HANDOFF_ERROR_ZH,
2930
+ [import_shared11.ERROR_CODES.ACTIVE_ADAPTER_CONFLICT]: EXTERNAL_HANDOFF_ERROR_ZH,
2931
+ [import_shared11.ERROR_CODES.ACTIVE_ADAPTER_LEASE_INVALID]: EXTERNAL_HANDOFF_ERROR_ZH,
2932
+ [import_shared11.ERROR_CODES.ACTIVE_DISPATCH_INVALID]: EXTERNAL_HANDOFF_ERROR_ZH,
2933
+ [import_shared11.ERROR_CODES.SESSION_NOT_FOUND]: EXTERNAL_HANDOFF_ERROR_ZH,
2934
+ [import_shared11.ERROR_CODES.SESSION_AMBIGUOUS]: EXTERNAL_HANDOFF_ERROR_ZH,
2935
+ [import_shared11.ERROR_CODES.SESSION_CLOSED]: EXTERNAL_HANDOFF_ERROR_ZH,
2936
+ [import_shared11.ERROR_CODES.WORKTREE_DIRTY]: "运行 AI 前,请明确同意将当前本地修改纳入隔离基线。",
2937
+ [import_shared11.ERROR_CODES.WORKTREE_NOT_REPOSITORY]: "Vite 根目录不是已初始化 Git 仓库的顶层目录。",
2938
+ [import_shared11.ERROR_CODES.WORKTREE_OPERATION_IN_PROGRESS]: "请先完成当前 merge、rebase、cherry-pick 或 revert,再运行 AI。",
2939
+ [import_shared11.ERROR_CODES.WORKTREE_CONFLICTED]: "请先解决全部 Git 冲突,再运行 AI。",
2940
+ [import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_TOO_LARGE]: "未跟踪文件超过安全数量或体积上限,请先精简。",
2941
+ [import_shared11.ERROR_CODES.WORKTREE_UNTRACKED_UNSUPPORTED]: "未跟踪项已丢失、是符号链接或不是普通文件。",
2942
+ [import_shared11.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED]: "当前本地修改无法安全隔离。",
2943
+ [import_shared11.ERROR_CODES.TOOL_DENIED]: "工具请求违反本地安全策略。",
2944
+ [import_shared11.ERROR_CODES.TOOL_INPUT_INVALID]: "工具请求无效。",
2945
+ [import_shared11.ERROR_CODES.TOOL_ARGUMENTS_INVALID]: "工具参数无效。",
2946
+ [import_shared11.ERROR_CODES.TOOL_CALL_ID_CONFLICT]: "本轮工具 ID 冲突。",
2947
+ [import_shared11.ERROR_CODES.TOOL_PATH_DENIED]: "模型请求了受保护或项目外路径。",
2948
+ [import_shared11.ERROR_CODES.PATCH_REJECTED]: "补丁违反本地策略。",
2949
+ [import_shared11.ERROR_CODES.VALIDATION_FAILED]: "必需检查失败,无法应用变更。",
2950
+ [import_shared11.ERROR_CODES.APPLY_CONFLICT]: "Agent 触及文件已变化,未覆盖。",
2951
+ [import_shared11.ERROR_CODES.INTERNAL_ERROR]: "Agent 失败,未暴露私有细节。"
2861
2952
  });
2862
2953
  var SUMMARY_MESSAGES_EN = Object.freeze({
2954
+ instance: "Selected instance",
2955
+ instanceStates: {
2956
+ captured: "Captured element; locator describes selection time",
2957
+ changed: "Page content changed; snapshot preserved. Select again to confirm the current instance",
2958
+ detached: "Element unloaded; historical snapshot preserved",
2959
+ restored: "Restored snapshot; not bound to the current page"
2960
+ },
2863
2961
  adapter: "React adapter",
2864
2962
  api: "API",
2865
2963
  apiStatuses: Object.freeze({
@@ -2900,6 +2998,13 @@ var SUMMARY_MESSAGES_EN = Object.freeze({
2900
2998
  warning: "Warning"
2901
2999
  });
2902
3000
  var SUMMARY_MESSAGES_ZH = Object.freeze({
3001
+ instance: "选中实例",
3002
+ instanceStates: {
3003
+ captured: "已捕获元素;定位信息对应选择时刻",
3004
+ changed: "页面内容已变化,已保留快照;请重新选择以确认当前实例",
3005
+ detached: "元素已卸载,已保留历史快照",
3006
+ restored: "已恢复历史快照,未绑定当前页面"
3007
+ },
2903
3008
  adapter: "React 适配器",
2904
3009
  api: "API",
2905
3010
  apiStatuses: Object.freeze({
@@ -3084,13 +3189,13 @@ var UI_MESSAGES = Object.freeze({
3084
3189
  addCancelled: "Additional selection cancelled.",
3085
3190
  selectionLimit: (maximum) => `The selection limit of ${String(maximum)} elements has been reached.`,
3086
3191
  chooseAdditional: (selected, maximum) => `Choose another element. ${String(selected)} of ${String(maximum)} selected.`,
3087
- duplicate: "That source target is already selected.",
3192
+ duplicate: "That page element is already selected.",
3193
+ instanceBudgetExceeded: "The prompt cannot preserve every selected instance within its budget. Remove some targets or increase the context budget.",
3088
3194
  sourceProbable: "A probable React component was found without an authorized file token.",
3089
3195
  sourceMissing: "No authorized source marker was found for the selected element.",
3090
3196
  noSelectable: "No selectable element was found.",
3091
3197
  allTargetsRemoved: "All targets were removed. Choose an element to continue.",
3092
3198
  targetRemoved: "Selected target removed.",
3093
- detachedTargetPreserved: "The page element was unloaded; its collected context remains selected.",
3094
3199
  contextWarning: "Browser context collection completed with a warning.",
3095
3200
  contextCollected: "Browser context collected.",
3096
3201
  editorOpening: "Opening source…",
@@ -3248,13 +3353,13 @@ var UI_MESSAGES = Object.freeze({
3248
3353
  addCancelled: "已取消追加选择。",
3249
3354
  selectionLimit: (maximum) => `已达到 ${String(maximum)} 个元素的选择上限。`,
3250
3355
  chooseAdditional: (selected, maximum) => `请选择另一个元素,当前已选 ${String(selected)} / ${String(maximum)}。`,
3251
- duplicate: "该源码目标已经在当前选择中。",
3356
+ duplicate: "该页面元素已经在当前选择中。",
3357
+ instanceBudgetExceeded: "上下文预算无法完整保留所有选中实例,请减少目标数量或提高上下文预算。",
3252
3358
  sourceProbable: "找到可能的 React 组件,但没有获授权的源码标记。",
3253
3359
  sourceMissing: "选中元素没有获授权的源码标记。",
3254
3360
  noSelectable: "当前位置没有可选择的元素。",
3255
3361
  allTargetsRemoved: "已移除全部目标,请重新选择元素。",
3256
3362
  targetRemoved: "已移除选中目标。",
3257
- detachedTargetPreserved: "页面元素已卸载,已采集的上下文仍保留在选择中。",
3258
3363
  contextWarning: "浏览器上下文采集完成,但存在警告。",
3259
3364
  contextCollected: "浏览器上下文采集完成。",
3260
3365
  editorOpening: "正在打开源码……",
@@ -4574,7 +4679,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
4574
4679
  headerControls.className = "spotpatch-header-controls";
4575
4680
  const repositoryLink = createMarkedElement(document, "a");
4576
4681
  repositoryLink.className = "spotpatch-repository";
4577
- repositoryLink.href = import_shared7.SPOTPATCH_REPOSITORY_URL;
4682
+ repositoryLink.href = import_shared12.SPOTPATCH_REPOSITORY_URL;
4578
4683
  repositoryLink.target = "_blank";
4579
4684
  repositoryLink.rel = "noopener noreferrer";
4580
4685
  const localeButton = createButton(document, "", "spotpatch-locale");
@@ -5086,6 +5191,9 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
5086
5191
  requestFloatingSurfaceLayout();
5087
5192
  }
5088
5193
  function statusText(target2) {
5194
+ if (target2.instanceState !== void 0 && target2.instanceState !== "captured") {
5195
+ return messages.summary.instanceStates[target2.instanceState];
5196
+ }
5089
5197
  if (target2.status === "ready") {
5090
5198
  return messages.targets.statusReady;
5091
5199
  }
@@ -5128,14 +5236,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
5128
5236
  completeCount,
5129
5237
  targets.length
5130
5238
  );
5131
- const instructionLimitExceeded = instructionCharacters > import_shared7.MAX_ANNOTATION_INSTRUCTION_CHARACTERS;
5239
+ const instructionLimitExceeded = instructionCharacters > import_shared12.MAX_ANNOTATION_INSTRUCTION_CHARACTERS;
5132
5240
  targetBudget.dataset.state = instructionLimitExceeded ? "over" : "ready";
5133
5241
  targetBudget.textContent = instructionLimitExceeded ? messages.targets.instructionBudgetExceeded(
5134
5242
  instructionCharacters,
5135
- import_shared7.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5243
+ import_shared12.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5136
5244
  ) : messages.targets.instructionBudget(
5137
5245
  instructionCharacters,
5138
- import_shared7.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5246
+ import_shared12.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5139
5247
  );
5140
5248
  addTargetButton.disabled = !editingEnabled || targets.length >= maximum;
5141
5249
  addTargetButton.title = targets.length >= maximum ? messages.targets.limitTitle(maximum) : messages.targets.addTitle;
@@ -5195,12 +5303,12 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
5195
5303
  characterCount.className = "spotpatch-target-editor-count";
5196
5304
  characterCount.textContent = messages.targets.instructionCount(
5197
5305
  target2.instruction.length,
5198
- import_shared7.MAX_TARGET_INSTRUCTION_CHARACTERS
5306
+ import_shared12.MAX_TARGET_INSTRUCTION_CHARACTERS
5199
5307
  );
5200
5308
  editorHead.append(editorLabel, characterCount);
5201
5309
  const input = createMarkedElement(document, "textarea");
5202
5310
  input.rows = 4;
5203
- input.maxLength = import_shared7.MAX_TARGET_INSTRUCTION_CHARACTERS;
5311
+ input.maxLength = import_shared12.MAX_TARGET_INSTRUCTION_CHARACTERS;
5204
5312
  input.value = target2.instruction;
5205
5313
  input.placeholder = messages.targets.instructionPlaceholder;
5206
5314
  input.disabled = !editingEnabled;
@@ -5243,7 +5351,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
5243
5351
  if (count !== null) {
5244
5352
  count.textContent = messages.targets.instructionCount(
5245
5353
  instruction.length,
5246
- import_shared7.MAX_TARGET_INSTRUCTION_CHARACTERS
5354
+ import_shared12.MAX_TARGET_INSTRUCTION_CHARACTERS
5247
5355
  );
5248
5356
  }
5249
5357
  const completeCount = currentTargets.filter(
@@ -5258,14 +5366,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
5258
5366
  (total, target2) => total + target2.instruction.trim().length,
5259
5367
  0
5260
5368
  );
5261
- const instructionLimitExceeded = instructionCharacters > import_shared7.MAX_ANNOTATION_INSTRUCTION_CHARACTERS;
5369
+ const instructionLimitExceeded = instructionCharacters > import_shared12.MAX_ANNOTATION_INSTRUCTION_CHARACTERS;
5262
5370
  targetBudget.dataset.state = instructionLimitExceeded ? "over" : "ready";
5263
5371
  targetBudget.textContent = instructionLimitExceeded ? messages.targets.instructionBudgetExceeded(
5264
5372
  instructionCharacters,
5265
- import_shared7.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5373
+ import_shared12.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5266
5374
  ) : messages.targets.instructionBudget(
5267
5375
  instructionCharacters,
5268
- import_shared7.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5376
+ import_shared12.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5269
5377
  );
5270
5378
  }
5271
5379
  function showSelectionHighlights(targets) {
@@ -5386,7 +5494,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
5386
5494
  targetBudget.dataset.state = "ready";
5387
5495
  targetBudget.textContent = messages.targets.instructionBudget(
5388
5496
  0,
5389
- import_shared7.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5497
+ import_shared12.MAX_ANNOTATION_INSTRUCTION_CHARACTERS
5390
5498
  );
5391
5499
  targetLabel.textContent = messages.context.selectedElement;
5392
5500
  }
@@ -5726,6 +5834,11 @@ function createSelectionSummary(input, messages) {
5726
5834
  `${messages.confidence}: ${input.resolution.source.confidence} (${messages.confidenceLabels[input.resolution.source.confidence]})`,
5727
5835
  `${messages.origin}: ${input.resolution.source.origin}`
5728
5836
  ];
5837
+ if (input.instance !== void 0) {
5838
+ lines.push(
5839
+ `${messages.instance}: ${messages.instanceStates[input.instance.state]}`
5840
+ );
5841
+ }
5729
5842
  if (input.resolution.react.componentName !== void 0) {
5730
5843
  lines.push(`${messages.component}: ${input.resolution.react.componentName}`);
5731
5844
  }
@@ -5759,7 +5872,7 @@ function createSelectionSummary(input, messages) {
5759
5872
  }
5760
5873
 
5761
5874
  // src/controller/agent-workflow.ts
5762
- var import_shared8 = require("@spotpatch/shared");
5875
+ var import_shared13 = require("@spotpatch/shared");
5763
5876
  function capabilityKey(providerProfileId, modelProfileId) {
5764
5877
  return `${providerProfileId}:${modelProfileId}`;
5765
5878
  }
@@ -5797,7 +5910,7 @@ function activityFromEvent(event) {
5797
5910
  return void 0;
5798
5911
  }
5799
5912
  function createAgentWorkflow(options) {
5800
- const errorCode = (error) => runtimeApiErrorCode(error) ?? import_shared8.ERROR_CODES.INTERNAL_ERROR;
5913
+ const errorCode = (error) => runtimeApiErrorCode(error) ?? import_shared13.ERROR_CODES.INTERNAL_ERROR;
5801
5914
  const errorMessage = (error) => options.view.messages().errors[errorCode(error)];
5802
5915
  const capabilities = /* @__PURE__ */ new Map();
5803
5916
  const providerConsents = /* @__PURE__ */ new Set();
@@ -5883,7 +5996,7 @@ function createAgentWorkflow(options) {
5883
5996
  }
5884
5997
  if (capability.state !== "agent-ready") {
5885
5998
  throw new RuntimeApiError(
5886
- capability.errorCode ?? import_shared8.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED
5999
+ capability.errorCode ?? import_shared13.ERROR_CODES.MODEL_TOOL_CALL_UNSUPPORTED
5887
6000
  );
5888
6001
  }
5889
6002
  capabilities.set(key, capability);
@@ -6077,11 +6190,11 @@ function createAgentWorkflow(options) {
6077
6190
  }
6078
6191
  if (health.state === "blocked") {
6079
6192
  throw new RuntimeApiError(
6080
- health.errorCode ?? import_shared8.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED
6193
+ health.errorCode ?? import_shared13.ERROR_CODES.WORKTREE_LOCAL_CHANGES_UNSUPPORTED
6081
6194
  );
6082
6195
  }
6083
6196
  if (health.state === "consent-required" && !options.view.agentWorkspaceConsentGranted()) {
6084
- throw new RuntimeApiError(import_shared8.ERROR_CODES.WORKTREE_DIRTY);
6197
+ throw new RuntimeApiError(import_shared13.ERROR_CODES.WORKTREE_DIRTY);
6085
6198
  }
6086
6199
  const created = await options.api.createAgentJob({
6087
6200
  annotation,
@@ -6182,7 +6295,7 @@ function sourceLabel(target2, unavailable) {
6182
6295
  return `${path}${line === void 0 ? "" : `:${String(line)}`}${column === void 0 ? "" : `:${String(column)}`}`;
6183
6296
  }
6184
6297
  function targetStatus(target2) {
6185
- if (target2.apiStatus === "failed" || target2.collectionStatus === "failed") {
6298
+ if (target2.apiStatus === "failed" || target2.collectionStatus === "failed" || target2.elementContext?.instance !== void 0 && target2.elementContext.instance.state !== "captured") {
6186
6299
  return "warning";
6187
6300
  }
6188
6301
  if (target2.apiStatus === "loading" || target2.collectionStatus === "loading") {
@@ -6225,6 +6338,7 @@ function createController(config, dependencies = {}) {
6225
6338
  const now = dependencies.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
6226
6339
  const selectionSession = dependencies.selectionSession ?? createSelectionSession(browser.window, config.sessionId, config.maxTargets);
6227
6340
  const restoredSelection = selectionSession.load();
6341
+ const instanceNamespace = createBrowserAnnotationId(browser.window);
6228
6342
  const sourceResolver = createSourceResolver({
6229
6343
  adapter: dependencies.reactAdapter ?? (0, import_react_adapter.createReact18Adapter)({
6230
6344
  ...config.dataFlow.enabled ? {
@@ -6256,7 +6370,8 @@ function createController(config, dependencies = {}) {
6256
6370
  dataFlowReport: void 0,
6257
6371
  dataFlowStatus: "idle",
6258
6372
  element: void 0,
6259
- elementContext: target2.element,
6373
+ instanceScope: void 0,
6374
+ elementContext: withInstanceState(target2.element, "restored"),
6260
6375
  instruction: target2.instruction,
6261
6376
  marker,
6262
6377
  page: target2.page,
@@ -6290,14 +6405,14 @@ function createController(config, dependencies = {}) {
6290
6405
  const react2 = target2.resolution.react;
6291
6406
  if (react2.componentSourceId !== void 0 && react2.sourceVersion !== void 0) {
6292
6407
  return Object.freeze({
6293
- schemaVersion: import_shared9.DATA_FLOW_SCHEMA_VERSION,
6408
+ schemaVersion: import_shared14.DATA_FLOW_SCHEMA_VERSION,
6294
6409
  componentSourceId: react2.componentSourceId,
6295
6410
  sourceVersion: react2.sourceVersion
6296
6411
  });
6297
6412
  }
6298
6413
  const marker = target2.marker;
6299
6414
  return marker === void 0 ? void 0 : Object.freeze({
6300
- schemaVersion: import_shared9.DATA_FLOW_SCHEMA_VERSION,
6415
+ schemaVersion: import_shared14.DATA_FLOW_SCHEMA_VERSION,
6301
6416
  fileId: marker.fileId,
6302
6417
  line: marker.line,
6303
6418
  column: marker.column
@@ -6345,7 +6460,7 @@ function createController(config, dependencies = {}) {
6345
6460
  const [componentResult, pageResult] = await Promise.allSettled([
6346
6461
  currentRequest === void 0 ? Promise.resolve(void 0) : api.componentDataFlowReport(currentRequest),
6347
6462
  pageTargets.length === 0 ? Promise.resolve(void 0) : api.pageDataFlowReport({
6348
- schemaVersion: import_shared9.DATA_FLOW_SCHEMA_VERSION,
6463
+ schemaVersion: import_shared14.DATA_FLOW_SCHEMA_VERSION,
6349
6464
  targets: pageTargets
6350
6465
  })
6351
6466
  ]);
@@ -6410,11 +6525,12 @@ function createController(config, dependencies = {}) {
6410
6525
  (total, target2) => total + target2.instruction.trim().length,
6411
6526
  0
6412
6527
  );
6413
- return targets.length > 0 && instructionCharacters <= import_shared9.MAX_ANNOTATION_INSTRUCTION_CHARACTERS && targets.every(
6528
+ return targets.length > 0 && instructionCharacters <= import_shared14.MAX_ANNOTATION_INSTRUCTION_CHARACTERS && targets.every(
6414
6529
  (target2) => target2.instruction.trim().length > 0 && target2.elementContext !== void 0 && target2.styles !== void 0 && target2.apiStatus !== "loading"
6415
6530
  );
6416
6531
  }
6417
6532
  function selectedAskSelection() {
6533
+ refreshInstanceStates(mutationObserver?.takeRecords() ?? []);
6418
6534
  const snapshots = targets.flatMap((target2) => {
6419
6535
  const snapshot = snapshotTarget(target2);
6420
6536
  return snapshot === void 0 ? [] : [snapshot];
@@ -6433,6 +6549,7 @@ function createController(config, dependencies = {}) {
6433
6549
  const summary = createSelectionSummary(
6434
6550
  {
6435
6551
  resolution: target2.resolution,
6552
+ ...target2.elementContext?.instance === void 0 ? {} : { instance: target2.elementContext.instance },
6436
6553
  ...target2.code === void 0 ? {} : { code: target2.code },
6437
6554
  ...target2.styles === void 0 ? {} : { styles: target2.styles },
6438
6555
  apiStatus: target2.apiStatus,
@@ -6478,7 +6595,11 @@ ${summary}`;
6478
6595
  view.renderTargets(
6479
6596
  targets.map((target2) => ({
6480
6597
  id: target2.id,
6481
- label: target2.resolution.react.componentName ?? (target2.element === void 0 ? target2.elementContext?.tagName ?? "Element" : elementLabel(target2.element)),
6598
+ ...target2.elementContext?.instance === void 0 ? {} : { instanceState: target2.elementContext.instance.state },
6599
+ label: [
6600
+ target2.resolution.react.componentName ?? target2.elementContext?.tagName ?? "Element",
6601
+ (target2.elementContext?.instance?.label ?? target2.elementContext?.textPreview)?.slice(0, 80)
6602
+ ].filter(Boolean).join(" · "),
6482
6603
  source: sourceLabel(target2, view.messages().context.sourceUnavailable),
6483
6604
  canOpenEditor: target2.marker !== void 0,
6484
6605
  status: targetStatus(target2),
@@ -6498,6 +6619,7 @@ ${summary}`;
6498
6619
  }
6499
6620
  }
6500
6621
  function selectedAnnotation() {
6622
+ refreshInstanceStates(mutationObserver?.takeRecords() ?? []);
6501
6623
  if (!canPreview()) {
6502
6624
  return void 0;
6503
6625
  }
@@ -6650,6 +6772,9 @@ ${summary}`;
6650
6772
  resizeObserver?.disconnect();
6651
6773
  for (const target2 of targets) {
6652
6774
  target2.element = void 0;
6775
+ target2.instanceScope = void 0;
6776
+ if (target2.elementContext !== void 0)
6777
+ target2.elementContext = withInstanceState(target2.elementContext, "detached");
6653
6778
  }
6654
6779
  view.hideHighlight();
6655
6780
  view.hideSelectionHighlights();
@@ -6737,17 +6862,11 @@ ${summary}`;
6737
6862
  if (!targetIsCurrent(target2, revision)) {
6738
6863
  return;
6739
6864
  }
6740
- let failed = false;
6741
- try {
6742
- target2.elementContext = collectElementContext({
6743
- element: element2,
6744
- maxCharacters: config.budget.domCharacters
6745
- });
6746
- } catch {
6747
- target2.elementContext = void 0;
6748
- failed = true;
6749
- }
6865
+ refreshInstanceStates(mutationObserver?.takeRecords() ?? []);
6866
+ let failed = target2.elementContext === void 0;
6750
6867
  try {
6868
+ if (target2.element !== element2)
6869
+ throw new Error("Selected instance changed before style collection.");
6751
6870
  target2.styles = collectStyleContext({
6752
6871
  document: browser.document,
6753
6872
  element: element2,
@@ -6771,18 +6890,11 @@ ${summary}`;
6771
6890
  }, 0);
6772
6891
  collectionTimers.set(target2.id, timer);
6773
6892
  }
6774
- function duplicateTarget(element2, marker) {
6775
- if (marker !== void 0) {
6776
- return targets.find(
6777
- (target2) => target2.marker?.fileId === marker.fileId && target2.marker.line === marker.line && target2.marker.column === marker.column
6778
- );
6779
- }
6780
- return targets.find((target2) => target2.element === element2);
6781
- }
6782
6893
  function selectElement(element2) {
6894
+ refreshInstanceStates(mutationObserver?.takeRecords() ?? []);
6783
6895
  const resolution = sourceResolver.resolve(element2);
6784
6896
  const marker = sourceRefToMarker(resolution.source);
6785
- const duplicate = duplicateTarget(element2, marker);
6897
+ const duplicate = targets.find((target3) => target3.element === element2);
6786
6898
  if (duplicate !== void 0) {
6787
6899
  activeTargetId = duplicate.id;
6788
6900
  addingTarget = false;
@@ -6814,6 +6926,7 @@ ${summary}`;
6814
6926
  const target2 = {
6815
6927
  id: `target-${String(targetSequence)}`,
6816
6928
  element: element2,
6929
+ instanceScope: void 0,
6817
6930
  resolution,
6818
6931
  marker,
6819
6932
  page: collectPageContext(browser.document, browser.window),
@@ -6826,6 +6939,17 @@ ${summary}`;
6826
6939
  dataFlowReport: void 0,
6827
6940
  dataFlowStatus: "idle"
6828
6941
  };
6942
+ try {
6943
+ const capture = captureSelectedInstance(
6944
+ element2,
6945
+ `${instanceNamespace}_${target2.id}`,
6946
+ config.budget.domCharacters
6947
+ );
6948
+ target2.elementContext = capture.context;
6949
+ target2.instanceScope = capture.scope;
6950
+ } catch {
6951
+ target2.collectionStatus = "failed";
6952
+ }
6829
6953
  targets.push(target2);
6830
6954
  if (!initialSelection) {
6831
6955
  contextualAskWorkflow?.selectionChanged();
@@ -6956,25 +7080,32 @@ ${summary}`;
6956
7080
  persistSelection();
6957
7081
  view.announce(view.messages().announcements.targetRemoved);
6958
7082
  }
6959
- function refreshSelectedGeometry() {
6960
- if (state.status === "idle" || targets.length === 0) {
6961
- return;
7083
+ function refreshInstanceStates(records) {
7084
+ let changed = false;
7085
+ for (const target2 of targets) {
7086
+ if (target2.element === void 0) continue;
7087
+ const next = target2.page.url !== browser.window.location.href ? "changed" : changedInstanceState(
7088
+ target2.element,
7089
+ target2.instanceScope ?? target2.element,
7090
+ records
7091
+ );
7092
+ if (next === void 0) continue;
7093
+ resizeObserver?.unobserve(target2.element);
7094
+ target2.element = void 0;
7095
+ target2.instanceScope = void 0;
7096
+ if (target2.elementContext !== void 0)
7097
+ target2.elementContext = withInstanceState(target2.elementContext, next);
7098
+ changed = true;
6962
7099
  }
6963
- const disconnected = targets.filter(
6964
- (target2) => target2.element !== void 0 && !target2.element.isConnected
6965
- );
6966
- if (disconnected.length > 0) {
6967
- for (const target2 of disconnected) {
6968
- if (target2.element !== void 0) {
6969
- resizeObserver?.unobserve(target2.element);
6970
- target2.element = void 0;
6971
- }
6972
- }
7100
+ if (changed) {
6973
7101
  refreshSelectionView();
6974
7102
  persistSelection();
6975
- view.announce(view.messages().announcements.detachedTargetPreserved);
6976
- return;
7103
+ contextualAskWorkflow?.selectionChanged();
6977
7104
  }
7105
+ }
7106
+ function refreshSelectedGeometry() {
7107
+ if (state.status === "idle" || targets.length === 0) return;
7108
+ refreshInstanceStates(mutationObserver?.takeRecords() ?? []);
6978
7109
  refreshHighlights();
6979
7110
  }
6980
7111
  function handleOpenEditor(targetId) {
@@ -7028,6 +7159,15 @@ ${summary}`;
7028
7159
  agentWorkflow.run();
7029
7160
  }
7030
7161
  }
7162
+ function composeSelectionPrompt(annotation) {
7163
+ try {
7164
+ return promptComposer.compose(annotation);
7165
+ } catch (error) {
7166
+ if (!(error instanceof RangeError)) throw error;
7167
+ view.announce(view.messages().announcements.instanceBudgetExceeded);
7168
+ return void 0;
7169
+ }
7170
+ }
7031
7171
  function handlePreview() {
7032
7172
  if (state.status !== "selected") {
7033
7173
  return;
@@ -7037,7 +7177,9 @@ ${summary}`;
7037
7177
  view.announce(view.messages().announcements.completeInstructions);
7038
7178
  return;
7039
7179
  }
7040
- previewPrompt = promptComposer.compose(annotation);
7180
+ const composed = composeSelectionPrompt(annotation);
7181
+ if (composed === void 0) return;
7182
+ previewPrompt = composed;
7041
7183
  transition({ type: "PREVIEW" });
7042
7184
  view.showPreview(previewPrompt);
7043
7185
  view.focusPrompt();
@@ -7046,6 +7188,12 @@ ${summary}`;
7046
7188
  if (state.status !== "previewing" || previewPrompt.length === 0) {
7047
7189
  return;
7048
7190
  }
7191
+ const annotation = selectedAnnotation();
7192
+ if (annotation === void 0) return;
7193
+ const composed = composeSelectionPrompt(annotation);
7194
+ if (composed === void 0) return;
7195
+ previewPrompt = composed;
7196
+ view.showPreview(previewPrompt);
7049
7197
  if (clipboard === void 0) {
7050
7198
  transition({ type: "COPY_FAILURE" });
7051
7199
  view.focusPrompt();
@@ -7082,8 +7230,11 @@ ${summary}`;
7082
7230
  if (state.status === "previewing") {
7083
7231
  const annotation = selectedAnnotation();
7084
7232
  if (annotation !== void 0) {
7085
- previewPrompt = promptComposer.compose(annotation);
7086
- view.showPreview(previewPrompt);
7233
+ const composed = composeSelectionPrompt(annotation);
7234
+ if (composed !== void 0) {
7235
+ previewPrompt = composed;
7236
+ view.showPreview(previewPrompt);
7237
+ }
7087
7238
  }
7088
7239
  }
7089
7240
  }
@@ -7137,6 +7288,8 @@ ${summary}`;
7137
7288
  browser.document.addEventListener("keydown", handleKeydown, true);
7138
7289
  browser.window.addEventListener("scroll", refreshSelectedGeometry, true);
7139
7290
  browser.window.addEventListener("resize", refreshSelectedGeometry);
7291
+ browser.window.addEventListener("popstate", refreshSelectedGeometry);
7292
+ browser.window.addEventListener("hashchange", refreshSelectedGeometry);
7140
7293
  view.triggerButton.addEventListener("click", activate);
7141
7294
  view.addTargetButton.addEventListener("click", beginAddTarget);
7142
7295
  view.reselectButton.addEventListener("click", handleReselect);
@@ -7173,10 +7326,15 @@ ${summary}`;
7173
7326
  resizeObserver = new browser.resizeObserver(refreshSelectedGeometry);
7174
7327
  }
7175
7328
  if (browser.mutationObserver !== void 0) {
7176
- mutationObserver = new browser.mutationObserver(refreshSelectedGeometry);
7329
+ mutationObserver = new browser.mutationObserver((records) => {
7330
+ refreshInstanceStates(records);
7331
+ refreshHighlights();
7332
+ });
7177
7333
  mutationObserver.observe(browser.document.documentElement, {
7178
7334
  childList: true,
7179
- subtree: true
7335
+ subtree: true,
7336
+ attributes: true,
7337
+ characterData: true
7180
7338
  });
7181
7339
  }
7182
7340
  if (selectionOpen && targets.length > 0) {
@@ -7211,6 +7369,8 @@ ${summary}`;
7211
7369
  browser.document.removeEventListener("keydown", handleKeydown, true);
7212
7370
  browser.window.removeEventListener("scroll", refreshSelectedGeometry, true);
7213
7371
  browser.window.removeEventListener("resize", refreshSelectedGeometry);
7372
+ browser.window.removeEventListener("popstate", refreshSelectedGeometry);
7373
+ browser.window.removeEventListener("hashchange", refreshSelectedGeometry);
7214
7374
  view.triggerButton.removeEventListener("click", activate);
7215
7375
  view.addTargetButton.removeEventListener("click", beginAddTarget);
7216
7376
  view.reselectButton.removeEventListener("click", handleReselect);
@@ -7696,7 +7856,7 @@ function getDataFlowRuntime(target2 = globalThis) {
7696
7856
  }
7697
7857
 
7698
7858
  // src/data-flow/report-merger.ts
7699
- var import_shared10 = require("@spotpatch/shared");
7859
+ var import_shared15 = require("@spotpatch/shared");
7700
7860
  function observationMatchesDependency(observation, dependency) {
7701
7861
  const origin = dependency.origin;
7702
7862
  const transportMatches = dependency.kind === "rpc" ? observation.transport === "trpc" && dependency.operation !== void 0 && observation.operation === dependency.operation : dependency.kind === "http" ? observation.transport === "fetch" || observation.transport === "xhr" : false;
@@ -7766,7 +7926,7 @@ function mergeComponentDataFlowReport(report, observations) {
7766
7926
  (observation) => observation.componentSourceId === void 0 || owners.has(observation.componentSourceId)
7767
7927
  );
7768
7928
  const merged = mergeDependencies(report.dependencies, componentObservations);
7769
- return (0, import_shared10.limitDataFlowReportCollections)(
7929
+ return (0, import_shared15.limitDataFlowReportCollections)(
7770
7930
  Object.freeze({
7771
7931
  ...report,
7772
7932
  dependencies: merged.dependencies,
@@ -7795,7 +7955,7 @@ function unassignedDependency(observation) {
7795
7955
  (path) => Object.freeze({
7796
7956
  path,
7797
7957
  position: "query",
7798
- sensitive: (0, import_shared10.isSensitiveName)(path),
7958
+ sensitive: (0, import_shared15.isSensitiveName)(path),
7799
7959
  valueState: "not-collected",
7800
7960
  evidenceIds: Object.freeze([observation.id])
7801
7961
  })
@@ -7817,7 +7977,7 @@ function mergePageDataFlowReport(report, observations) {
7817
7977
  const merged = mergeDependencies(report.dependencies, currentObservations);
7818
7978
  const unassigned = currentObservations.filter(({ id }) => !merged.matchedObservationIds.has(id)).map(unassignedDependency);
7819
7979
  const allObservationIds = new Set(currentObservations.map(({ id }) => id));
7820
- return (0, import_shared10.limitDataFlowReportCollections)(
7980
+ return (0, import_shared15.limitDataFlowReportCollections)(
7821
7981
  Object.freeze({
7822
7982
  ...report,
7823
7983
  dependencies: Object.freeze([...merged.dependencies, ...unassigned]),