@blade-hq/agent-kit 0.5.6 → 0.5.10
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/{SkillStatusBar-CvNCQRtt.d.ts → SkillStatusBar-Dlf-_G5d.d.ts} +2 -2
- package/dist/{blade-client-B6xMtRwr.d.ts → blade-client-7VANnJfr.d.ts} +5 -1
- package/dist/{chunk-CBO2A567.js → chunk-ETHPRRT2.js} +9 -1
- package/dist/chunk-ETHPRRT2.js.map +1 -0
- package/dist/{chunk-VPWN6VS4.js → chunk-G2LJZTPX.js} +178 -93
- package/dist/chunk-G2LJZTPX.js.map +1 -0
- package/dist/{chunk-PX53WJ2C.js → chunk-GIE2Q2MB.js} +28 -16
- package/dist/chunk-GIE2Q2MB.js.map +1 -0
- package/dist/{chunk-T3G4VHAM.js → chunk-STCTXRMJ.js} +2 -2
- package/dist/{chunk-D7IT5PRL.js → chunk-UM7G65GH.js} +116 -20
- package/dist/chunk-UM7G65GH.js.map +1 -0
- package/dist/{chunk-NOUG4L43.js → chunk-X3S36RR2.js} +2 -2
- package/dist/client/index.d.ts +1051 -17
- package/dist/client/index.js +1 -1
- package/dist/react/api/vibe-coding.d.ts +3 -3
- package/dist/react/api/vibe-coding.js +2 -2
- package/dist/react/components/chat/index.d.ts +6 -5
- package/dist/react/components/chat/index.js +5 -5
- package/dist/react/components/plan/index.js +3 -3
- package/dist/react/components/session/index.d.ts +1 -1
- package/dist/react/components/session/index.js +3 -3
- package/dist/react/components/workspace/index.js +3 -3
- package/dist/react/index.d.ts +177 -8
- package/dist/react/index.js +469 -6
- package/dist/react/index.js.map +1 -1
- package/dist/{session-ADRevzHD.d.ts → session-BuaeCsMC.d.ts} +62 -2
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/dist/chunk-CBO2A567.js.map +0 -1
- package/dist/chunk-D7IT5PRL.js.map +0 -1
- package/dist/chunk-PX53WJ2C.js.map +0 -1
- package/dist/chunk-VPWN6VS4.js.map +0 -1
- /package/dist/{chunk-T3G4VHAM.js.map → chunk-STCTXRMJ.js.map} +0 -0
- /package/dist/{chunk-NOUG4L43.js.map → chunk-X3S36RR2.js.map} +0 -0
package/dist/react/index.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
useTiptapVoiceInput,
|
|
31
31
|
useVoiceInput,
|
|
32
32
|
user_preferences_exports
|
|
33
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-G2LJZTPX.js";
|
|
34
34
|
import {
|
|
35
35
|
CardCodeBlock,
|
|
36
36
|
CardContext,
|
|
@@ -39,18 +39,18 @@ import {
|
|
|
39
39
|
normalizeCodeLanguage,
|
|
40
40
|
useCardContext,
|
|
41
41
|
useHighlightedCodeHtml
|
|
42
|
-
} from "../chunk-
|
|
42
|
+
} from "../chunk-GIE2Q2MB.js";
|
|
43
43
|
import {
|
|
44
44
|
CardJSON,
|
|
45
45
|
cardRegistry
|
|
46
46
|
} from "../chunk-2UP7MG3J.js";
|
|
47
47
|
import {
|
|
48
48
|
useSession
|
|
49
|
-
} from "../chunk-
|
|
49
|
+
} from "../chunk-STCTXRMJ.js";
|
|
50
50
|
import {
|
|
51
51
|
buildSessionBinaryPreviewTarget,
|
|
52
52
|
resolveSessionFilePreviewTarget
|
|
53
|
-
} from "../chunk-
|
|
53
|
+
} from "../chunk-X3S36RR2.js";
|
|
54
54
|
import {
|
|
55
55
|
PartnerSkillFile,
|
|
56
56
|
PartnerSkillInstallPayload,
|
|
@@ -102,12 +102,12 @@ import {
|
|
|
102
102
|
useTaskStore,
|
|
103
103
|
useUiBridgeStore,
|
|
104
104
|
useUiStore
|
|
105
|
-
} from "../chunk-
|
|
105
|
+
} from "../chunk-UM7G65GH.js";
|
|
106
106
|
import "../chunk-J3XVFPOV.js";
|
|
107
107
|
import {
|
|
108
108
|
REGISTRY_PREFIX,
|
|
109
109
|
normalizeResource
|
|
110
|
-
} from "../chunk-
|
|
110
|
+
} from "../chunk-ETHPRRT2.js";
|
|
111
111
|
import {
|
|
112
112
|
cn,
|
|
113
113
|
copyToClipboard
|
|
@@ -1132,6 +1132,466 @@ function deriveDeprecateEntryIds(stepRanges, messages, fromStep) {
|
|
|
1132
1132
|
return ids;
|
|
1133
1133
|
}
|
|
1134
1134
|
|
|
1135
|
+
// src/react/lib/html-source-locator.ts
|
|
1136
|
+
var SNIPPET_LIMIT = 2e3;
|
|
1137
|
+
var TEXT_ANCHOR_LIMIT = 120;
|
|
1138
|
+
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
1139
|
+
"area",
|
|
1140
|
+
"base",
|
|
1141
|
+
"br",
|
|
1142
|
+
"col",
|
|
1143
|
+
"embed",
|
|
1144
|
+
"hr",
|
|
1145
|
+
"img",
|
|
1146
|
+
"input",
|
|
1147
|
+
"link",
|
|
1148
|
+
"meta",
|
|
1149
|
+
"param",
|
|
1150
|
+
"source",
|
|
1151
|
+
"track",
|
|
1152
|
+
"wbr"
|
|
1153
|
+
]);
|
|
1154
|
+
var STABLE_ATTRS = ["data-blade-id", "data-testid", "data-cy", "id"];
|
|
1155
|
+
function escapeRegExp(value) {
|
|
1156
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1157
|
+
}
|
|
1158
|
+
function normalizeTag(tag) {
|
|
1159
|
+
return tag.trim().toLowerCase().replace(/[^a-z0-9:-]/g, "") || "*";
|
|
1160
|
+
}
|
|
1161
|
+
function normalizeText(text) {
|
|
1162
|
+
return text.replace(/\s+/g, " ").trim();
|
|
1163
|
+
}
|
|
1164
|
+
function truncate(value, limit) {
|
|
1165
|
+
if (value.length <= limit) return value;
|
|
1166
|
+
return `${value.slice(0, Math.max(0, limit - 1))}\u2026`;
|
|
1167
|
+
}
|
|
1168
|
+
function lineColumnAt(content, index) {
|
|
1169
|
+
const before = content.slice(0, Math.max(0, index));
|
|
1170
|
+
const lines = before.split("\n");
|
|
1171
|
+
return { line: lines.length, column: lines[lines.length - 1].length + 1 };
|
|
1172
|
+
}
|
|
1173
|
+
function buildTagPattern(tag, innerPattern) {
|
|
1174
|
+
const tagPart = tag === "*" ? "[a-zA-Z][\\w:-]*" : escapeRegExp(tag);
|
|
1175
|
+
return new RegExp(`<${tagPart}\\b(?=[^>]*${innerPattern})[^>]*>`, "gi");
|
|
1176
|
+
}
|
|
1177
|
+
function attrPattern(attr, value) {
|
|
1178
|
+
const escapedAttr = escapeRegExp(attr);
|
|
1179
|
+
const escapedValue = escapeRegExp(value);
|
|
1180
|
+
return `\\b${escapedAttr}\\s*=\\s*(?:"${escapedValue}"|'${escapedValue}'|${escapedValue}(?=\\s|>|/))`;
|
|
1181
|
+
}
|
|
1182
|
+
function collectMatches(pattern, content) {
|
|
1183
|
+
const matches = [];
|
|
1184
|
+
pattern.lastIndex = 0;
|
|
1185
|
+
let match = pattern.exec(content);
|
|
1186
|
+
while (match != null) {
|
|
1187
|
+
matches.push(match);
|
|
1188
|
+
if (match[0].length === 0) pattern.lastIndex += 1;
|
|
1189
|
+
match = pattern.exec(content);
|
|
1190
|
+
}
|
|
1191
|
+
return matches;
|
|
1192
|
+
}
|
|
1193
|
+
function findOpeningTagByAttr(content, tag, attr, value) {
|
|
1194
|
+
if (!value.trim()) return null;
|
|
1195
|
+
const matches = collectMatches(buildTagPattern(tag, attrPattern(attr, value)), content);
|
|
1196
|
+
if (matches.length !== 1) return null;
|
|
1197
|
+
return { index: matches[0].index, text: matches[0][0] };
|
|
1198
|
+
}
|
|
1199
|
+
function findOpeningTagNearText(content, tag, visibleText) {
|
|
1200
|
+
const text = normalizeText(visibleText);
|
|
1201
|
+
if (!text || text.length > TEXT_ANCHOR_LIMIT) return null;
|
|
1202
|
+
const textMatches = collectMatches(new RegExp(escapeRegExp(text), "g"), normalizeText(content));
|
|
1203
|
+
if (textMatches.length !== 1) return null;
|
|
1204
|
+
const originalIndex = content.indexOf(text);
|
|
1205
|
+
if (originalIndex < 0) return null;
|
|
1206
|
+
const normalizedTag = normalizeTag(tag);
|
|
1207
|
+
const tagPart = normalizedTag === "*" ? "[a-zA-Z][\\w:-]*" : escapeRegExp(normalizedTag);
|
|
1208
|
+
const openPattern = new RegExp(`<${tagPart}\\b[^>]*>`, "gi");
|
|
1209
|
+
let candidate = null;
|
|
1210
|
+
let match = openPattern.exec(content);
|
|
1211
|
+
while (match != null) {
|
|
1212
|
+
if (match.index > originalIndex) break;
|
|
1213
|
+
candidate = match;
|
|
1214
|
+
match = openPattern.exec(content);
|
|
1215
|
+
}
|
|
1216
|
+
if (!candidate) return null;
|
|
1217
|
+
return { index: candidate.index, text: candidate[0] };
|
|
1218
|
+
}
|
|
1219
|
+
function findSnippetEnd(content, start, tag, openingText) {
|
|
1220
|
+
const openingEnd = start + openingText.length;
|
|
1221
|
+
const normalizedTag = normalizeTag(tag);
|
|
1222
|
+
if (VOID_TAGS.has(normalizedTag) || openingText.endsWith("/>")) return openingEnd;
|
|
1223
|
+
const closePattern = new RegExp(`</${escapeRegExp(normalizedTag)}>`, "i");
|
|
1224
|
+
const closeMatch = closePattern.exec(content.slice(openingEnd));
|
|
1225
|
+
if (!closeMatch) return openingEnd;
|
|
1226
|
+
return openingEnd + closeMatch.index + closeMatch[0].length;
|
|
1227
|
+
}
|
|
1228
|
+
function buildSnippet(content, start, tag, openingText) {
|
|
1229
|
+
const rawEnd = findSnippetEnd(content, start, tag, openingText);
|
|
1230
|
+
const boundedEnd = Math.min(rawEnd, start + SNIPPET_LIMIT);
|
|
1231
|
+
const snippet = content.slice(start, boundedEnd);
|
|
1232
|
+
const startPos = lineColumnAt(content, start);
|
|
1233
|
+
const endPos = lineColumnAt(content, boundedEnd);
|
|
1234
|
+
return {
|
|
1235
|
+
snippet: rawEnd > boundedEnd ? `${snippet}\u2026` : snippet,
|
|
1236
|
+
startLine: startPos.line,
|
|
1237
|
+
endLine: endPos.line,
|
|
1238
|
+
startColumn: startPos.column,
|
|
1239
|
+
endColumn: endPos.column
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
function locateHtmlElementSource(html, element) {
|
|
1243
|
+
const tag = normalizeTag(element.tag);
|
|
1244
|
+
const attributes = element.attributes ?? {};
|
|
1245
|
+
const visibleText = normalizeText(element.visibleText ?? "");
|
|
1246
|
+
const searchAnchors = [];
|
|
1247
|
+
for (const attr of STABLE_ATTRS) {
|
|
1248
|
+
const value = attributes[attr];
|
|
1249
|
+
if (!value) continue;
|
|
1250
|
+
searchAnchors.push(`${attr}="${truncate(value, TEXT_ANCHOR_LIMIT)}"`);
|
|
1251
|
+
const found = findOpeningTagByAttr(html, tag, attr, value);
|
|
1252
|
+
if (found) {
|
|
1253
|
+
return {
|
|
1254
|
+
...buildSnippet(html, found.index, tag, found.text),
|
|
1255
|
+
searchAnchors,
|
|
1256
|
+
locatorConfidence: "high",
|
|
1257
|
+
reason: `${attr} \u53EF\u552F\u4E00\u5B9A\u4F4D`
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
const ariaLabel = attributes["aria-label"];
|
|
1262
|
+
if (ariaLabel) {
|
|
1263
|
+
searchAnchors.push(`aria-label="${truncate(ariaLabel, TEXT_ANCHOR_LIMIT)}"`);
|
|
1264
|
+
const found = findOpeningTagByAttr(html, tag, "aria-label", ariaLabel);
|
|
1265
|
+
if (found) {
|
|
1266
|
+
return {
|
|
1267
|
+
...buildSnippet(html, found.index, tag, found.text),
|
|
1268
|
+
searchAnchors,
|
|
1269
|
+
locatorConfidence: "medium",
|
|
1270
|
+
reason: "aria-label \u53EF\u552F\u4E00\u5B9A\u4F4D"
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
if (visibleText) {
|
|
1275
|
+
searchAnchors.push(`text="${truncate(visibleText, TEXT_ANCHOR_LIMIT)}"`);
|
|
1276
|
+
const found = findOpeningTagNearText(html, tag, visibleText);
|
|
1277
|
+
if (found) {
|
|
1278
|
+
return {
|
|
1279
|
+
...buildSnippet(html, found.index, tag, found.text),
|
|
1280
|
+
searchAnchors,
|
|
1281
|
+
locatorConfidence: "medium",
|
|
1282
|
+
reason: "\u53EF\u89C1\u6587\u5B57\u53EF\u552F\u4E00\u5B9A\u4F4D"
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
return {
|
|
1287
|
+
searchAnchors,
|
|
1288
|
+
locatorConfidence: "low",
|
|
1289
|
+
reason: "\u672A\u80FD\u5728\u6E90 HTML \u4E2D\u552F\u4E00\u5B9A\u4F4D\uFF0C\u9700\u7ED3\u5408\u6587\u4EF6\u5185\u5BB9\u4EBA\u5DE5\u6838\u5BF9"
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
// src/react/lib/html-element-selection.ts
|
|
1294
|
+
var VALUE_LIMIT = 240;
|
|
1295
|
+
var TEXT_LIMIT = 500;
|
|
1296
|
+
var STYLE_KEYS = /* @__PURE__ */ new Set([
|
|
1297
|
+
"display",
|
|
1298
|
+
"position",
|
|
1299
|
+
"color",
|
|
1300
|
+
"backgroundColor",
|
|
1301
|
+
"fontSize",
|
|
1302
|
+
"fontWeight",
|
|
1303
|
+
"margin",
|
|
1304
|
+
"padding"
|
|
1305
|
+
]);
|
|
1306
|
+
var SENSITIVE_NAME_RE = /(password|passwd|token|secret|authorization|api[-_]?key|cookie)/i;
|
|
1307
|
+
var URL_ATTRS = /* @__PURE__ */ new Set(["href", "src", "action"]);
|
|
1308
|
+
var USER_VALUE_ATTRS = /* @__PURE__ */ new Set(["value"]);
|
|
1309
|
+
function truncate2(value, limit, limits) {
|
|
1310
|
+
if (value.length <= limit) return value;
|
|
1311
|
+
limits.truncated = true;
|
|
1312
|
+
return `${value.slice(0, Math.max(0, limit - 1))}\u2026`;
|
|
1313
|
+
}
|
|
1314
|
+
function stripQueryAndHash(value) {
|
|
1315
|
+
try {
|
|
1316
|
+
const url = new URL(value, "http://blade.local");
|
|
1317
|
+
if (url.protocol === "http:" && url.host === "blade.local" && value.startsWith("/")) {
|
|
1318
|
+
return url.pathname;
|
|
1319
|
+
}
|
|
1320
|
+
url.search = "";
|
|
1321
|
+
url.hash = "";
|
|
1322
|
+
return url.toString();
|
|
1323
|
+
} catch {
|
|
1324
|
+
return value.split(/[?#]/, 1)[0];
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
function sanitizeAttributes(attributes, limits) {
|
|
1328
|
+
const result = {};
|
|
1329
|
+
for (const [key, rawValue] of Object.entries(attributes)) {
|
|
1330
|
+
const normalizedKey = key.trim();
|
|
1331
|
+
if (!normalizedKey) continue;
|
|
1332
|
+
if (SENSITIVE_NAME_RE.test(normalizedKey) || USER_VALUE_ATTRS.has(normalizedKey.toLowerCase())) {
|
|
1333
|
+
result[normalizedKey] = "[\u5DF2\u8131\u654F]";
|
|
1334
|
+
limits.omittedSensitiveFields.push(normalizedKey);
|
|
1335
|
+
continue;
|
|
1336
|
+
}
|
|
1337
|
+
const normalizedValue = URL_ATTRS.has(normalizedKey.toLowerCase()) ? stripQueryAndHash(rawValue) : rawValue;
|
|
1338
|
+
result[normalizedKey] = truncate2(normalizedValue, VALUE_LIMIT, limits);
|
|
1339
|
+
}
|
|
1340
|
+
return result;
|
|
1341
|
+
}
|
|
1342
|
+
function sanitizeStyle(style, limits) {
|
|
1343
|
+
const result = {};
|
|
1344
|
+
for (const [key, value] of Object.entries(style)) {
|
|
1345
|
+
if (!STYLE_KEYS.has(key)) continue;
|
|
1346
|
+
const normalizedKey = key.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
1347
|
+
result[normalizedKey] = truncate2(String(value), 80, limits);
|
|
1348
|
+
}
|
|
1349
|
+
return result;
|
|
1350
|
+
}
|
|
1351
|
+
function limitList(values, limits) {
|
|
1352
|
+
if (!values?.length) return void 0;
|
|
1353
|
+
if (values.length > 5) limits.truncated = true;
|
|
1354
|
+
return values.slice(0, 5).map((item) => truncate2(item, 160, limits));
|
|
1355
|
+
}
|
|
1356
|
+
function fileNameFromPath(filePath, fallback) {
|
|
1357
|
+
return fallback?.trim() || filePath.split("/").pop() || filePath || "\u672A\u547D\u540D HTML";
|
|
1358
|
+
}
|
|
1359
|
+
function elementKindLabel(selection) {
|
|
1360
|
+
const tag = selection.tag.toLowerCase();
|
|
1361
|
+
const role = selection.role?.toLowerCase();
|
|
1362
|
+
if (role === "button" || tag === "button") return "\u6309\u94AE";
|
|
1363
|
+
if (role === "link" || tag === "a") return "\u94FE\u63A5";
|
|
1364
|
+
if (role === "textbox" || tag === "input" || tag === "textarea") return "\u8F93\u5165\u6846";
|
|
1365
|
+
if (tag === "img") return "\u56FE\u7247";
|
|
1366
|
+
if (tag === "table") return "\u8868\u683C";
|
|
1367
|
+
if (tag === "tr") return "\u8868\u683C\u884C";
|
|
1368
|
+
if (tag === "td" || tag === "th") return "\u5355\u5143\u683C";
|
|
1369
|
+
if (/^h[1-6]$/.test(tag)) return "\u6807\u9898";
|
|
1370
|
+
if (tag === "section" || tag === "article" || tag === "div") return "\u533A\u57DF";
|
|
1371
|
+
return "\u5185\u5BB9";
|
|
1372
|
+
}
|
|
1373
|
+
function humanElementLabel(selection) {
|
|
1374
|
+
const kind = elementKindLabel(selection);
|
|
1375
|
+
const text = (selection.accessibleName || selection.visibleText || "").replace(/\s+/g, " ").trim();
|
|
1376
|
+
return text ? `${kind}\u300C${text.slice(0, 24)}${text.length > 24 ? "\u2026" : ""}\u300D` : `${kind}<${selection.tag}>`;
|
|
1377
|
+
}
|
|
1378
|
+
function stableSelectorsFromAttributes(attributes) {
|
|
1379
|
+
const selectors = [];
|
|
1380
|
+
const add = (kind, value, confidence) => {
|
|
1381
|
+
if (value && !selectors.some((item) => item.kind === kind && item.value === value)) {
|
|
1382
|
+
selectors.push({ kind, value, confidence });
|
|
1383
|
+
}
|
|
1384
|
+
};
|
|
1385
|
+
add("data-blade-id", attributes["data-blade-id"], "high");
|
|
1386
|
+
add("data-testid", attributes["data-testid"] || attributes["data-cy"], "high");
|
|
1387
|
+
add("id", attributes.id, "high");
|
|
1388
|
+
add("aria", attributes["aria-label"], "medium");
|
|
1389
|
+
return selectors;
|
|
1390
|
+
}
|
|
1391
|
+
function mergeSelectors(selection, attributes) {
|
|
1392
|
+
const selectors = [...stableSelectorsFromAttributes(attributes), ...selection.selectors ?? []];
|
|
1393
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1394
|
+
return selectors.filter((selector) => {
|
|
1395
|
+
if (!selector.value) return false;
|
|
1396
|
+
const key = `${selector.kind}:${selector.value}`;
|
|
1397
|
+
if (seen.has(key)) return false;
|
|
1398
|
+
seen.add(key);
|
|
1399
|
+
return true;
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
function sanitizeGroupItems(selection, limits) {
|
|
1403
|
+
const items = selection.groupItems ?? [];
|
|
1404
|
+
if (!items.length) return void 0;
|
|
1405
|
+
if (items.length > 12) limits.truncated = true;
|
|
1406
|
+
return items.slice(0, 12).map((item) => {
|
|
1407
|
+
const label = item.label ? truncate2(item.label.replace(/\s+/g, " ").trim(), 120, limits) : void 0;
|
|
1408
|
+
const visibleText = item.visibleText ? truncate2(item.visibleText.replace(/\s+/g, " ").trim(), 240, limits) : void 0;
|
|
1409
|
+
const accessibleName = item.accessibleName ? truncate2(item.accessibleName.replace(/\s+/g, " ").trim(), 160, limits) : void 0;
|
|
1410
|
+
return {
|
|
1411
|
+
label,
|
|
1412
|
+
tag: item.tag.toLowerCase(),
|
|
1413
|
+
role: item.role,
|
|
1414
|
+
accessible_name: accessibleName,
|
|
1415
|
+
visible_text: visibleText,
|
|
1416
|
+
selectors: item.selectors ?? [],
|
|
1417
|
+
dom_path: item.domPath,
|
|
1418
|
+
rect: item.rect
|
|
1419
|
+
};
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
function simpleContentHash(content) {
|
|
1423
|
+
let hash = 2166136261;
|
|
1424
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
1425
|
+
hash ^= content.charCodeAt(index);
|
|
1426
|
+
hash = Math.imul(hash, 16777619);
|
|
1427
|
+
}
|
|
1428
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
1429
|
+
}
|
|
1430
|
+
function sourceToContext(source) {
|
|
1431
|
+
return {
|
|
1432
|
+
snippet: source.snippet,
|
|
1433
|
+
start_line: source.startLine,
|
|
1434
|
+
end_line: source.endLine,
|
|
1435
|
+
start_column: source.startColumn,
|
|
1436
|
+
end_column: source.endColumn,
|
|
1437
|
+
search_anchors: source.searchAnchors,
|
|
1438
|
+
locator_confidence: source.locatorConfidence,
|
|
1439
|
+
reason: source.reason
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
function contextMarkdown(context) {
|
|
1443
|
+
const source = context.source;
|
|
1444
|
+
const rect = context.element.rect;
|
|
1445
|
+
const rectText = rect ? `x=${Math.round(rect.x)}, y=${Math.round(rect.y)}, w=${Math.round(rect.width)}, h=${Math.round(rect.height)}` : "\u672A\u77E5";
|
|
1446
|
+
const isRunningPage = context.source_kind === "running_page";
|
|
1447
|
+
const selectors = context.element.selectors.length ? context.element.selectors.map((selector, index) => `${index + 1}. ${selector.kind}="${selector.value}"\uFF08${selector.confidence}\uFF09`).join("\n") : "\u65E0\u7A33\u5B9A\u9009\u62E9\u5668\uFF1B\u8BF7\u7ED3\u5408\u6E90\u7247\u6BB5\u548C\u641C\u7D22\u951A\u70B9\u5B9A\u4F4D\u3002";
|
|
1448
|
+
const anchors = source.search_anchors.length ? source.search_anchors.map((anchor) => `- ${anchor}`).join("\n") : "- \u65E0";
|
|
1449
|
+
const sourceSnippet = source.snippet?.trim() ? `
|
|
1450
|
+
|
|
1451
|
+
## \u6E90 HTML \u7247\u6BB5
|
|
1452
|
+
\`\`\`html
|
|
1453
|
+
${source.snippet.trim()}
|
|
1454
|
+
\`\`\`` : "";
|
|
1455
|
+
const groupText = context.group ? `
|
|
1456
|
+
|
|
1457
|
+
## \u7EC4\u5408\u9009\u533A
|
|
1458
|
+
\u7528\u6237\u6846\u9009\u7684\u662F\u4E00\u7EC4\u754C\u9762\u5185\u5BB9\uFF0C\u4E0D\u662F\u5355\u4E2A\u5B64\u7ACB\u5143\u7D20\u3002\u8BF7\u628A\u8FD9\u4E9B\u5185\u5BB9\u4F5C\u4E3A\u540C\u4E00\u4E2A\u8C03\u6574\u8303\u56F4\u5904\u7406\u3002
|
|
1459
|
+
${context.group.items.map((item, index) => {
|
|
1460
|
+
const name = item.visible_text || item.accessible_name || item.label || item.tag;
|
|
1461
|
+
const rect2 = item.rect ? ` x=${Math.round(item.rect.x)}, y=${Math.round(item.rect.y)}, w=${Math.round(item.rect.width)}, h=${Math.round(item.rect.height)}` : "";
|
|
1462
|
+
return `${index + 1}. ${item.tag}${item.role ? ` role=${item.role}` : ""}\uFF1A${name}${rect2}`;
|
|
1463
|
+
}).join("\n")}` : "";
|
|
1464
|
+
const targetLine = isRunningPage ? `- \u9875\u9762\uFF1A\`${context.preview.url || context.file.path}\`` : `- \u6587\u4EF6\uFF1A\`${context.file.path}\``;
|
|
1465
|
+
const sourceHint = isRunningPage ? "\u8FD9\u662F\u7528\u6237\u5728\u53F3\u4FA7\u9884\u89C8\u4E2D\u9009\u4E2D\u7684\u8FD0\u884C\u9875\u9762\u5185\u5BB9\u3002\u8BF7\u4F18\u5148\u6839\u636E\u9875\u9762 URL\u3001\u53EF\u89C1\u6587\u5B57\u3001\u7A33\u5B9A\u6807\u8BB0\u548C\u5468\u8FB9\u5143\u7D20\uFF0C\u5728\u524D\u7AEF\u6E90\u7801\u4E2D\u5B9A\u4F4D\u5BF9\u5E94\u7EC4\u4EF6\u6216\u9875\u9762\uFF1B\u4E0D\u8981\u8981\u6C42\u7528\u6237\u63D0\u4F9B data \u5C5E\u6027\u3002" : "\u8FD9\u662F\u7528\u6237\u5728\u53F3\u4FA7 HTML \u9884\u89C8\u4E2D\u9009\u4E2D\u7684\u754C\u9762\u5185\u5BB9\u3002\u8BF7\u4F18\u5148\u7F16\u8F91\u6307\u5B9A\u6587\u4EF6\uFF0C\u5E76\u7528\u6E90 HTML \u7247\u6BB5\u3001\u7A33\u5B9A\u6807\u8BB0\u548C\u53EF\u89C1\u6587\u5B57\u5B9A\u4F4D\uFF0C\u4E0D\u8981\u4F9D\u8D56\u622A\u56FE\u731C\u6D4B\u3002";
|
|
1466
|
+
const screenshotNote = context.screenshot ? context.screenshot.included ? "\n\n## \u9009\u4E2D\u533A\u57DF\u622A\u56FE\n\u5DF2\u968F\u672C\u6761\u6D88\u606F\u9644\u52A0\u4E3A\u56FE\u7247\u3002\u82E5\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF0C\u8BF7\u76F4\u63A5\u5FFD\u7565\u622A\u56FE\u5E76\u4F7F\u7528\u4E0A\u9762\u7684\u6587\u672C\u4E0A\u4E0B\u6587\u3002" : `
|
|
1467
|
+
|
|
1468
|
+
## \u9009\u4E2D\u533A\u57DF\u622A\u56FE
|
|
1469
|
+
\u622A\u56FE\u751F\u6210\u5931\u8D25${context.screenshot.reason ? `\uFF08${context.screenshot.reason}\uFF09` : ""}\uFF0C\u672C\u6761\u6D88\u606F\u4EC5\u5305\u542B\u6587\u672C\u4E0A\u4E0B\u6587\u3002` : "";
|
|
1470
|
+
const surroundings = [
|
|
1471
|
+
context.surroundings.parent_summary ? `- \u7236\u7EA7\uFF1A${context.surroundings.parent_summary}` : null,
|
|
1472
|
+
...(context.surroundings.previous_siblings ?? []).map((item) => `- \u524D\u4E00\u4E2A\u5143\u7D20\uFF1A${item}`),
|
|
1473
|
+
...(context.surroundings.next_siblings ?? []).map((item) => `- \u540E\u4E00\u4E2A\u5143\u7D20\uFF1A${item}`)
|
|
1474
|
+
].filter(Boolean);
|
|
1475
|
+
return `${sourceHint}
|
|
1476
|
+
|
|
1477
|
+
## \u7528\u6237\u9009\u4E2D
|
|
1478
|
+
${targetLine}
|
|
1479
|
+
- \u5143\u7D20\uFF1A${context.element.label}
|
|
1480
|
+
- \u4F4D\u7F6E\uFF1A${rectText}
|
|
1481
|
+
- \u6E90\u5B9A\u4F4D\uFF1A${source.locator_confidence}\uFF08${source.reason}\uFF09
|
|
1482
|
+
|
|
1483
|
+
## \u7A33\u5B9A\u5B9A\u4F4D\u5019\u9009
|
|
1484
|
+
${selectors}
|
|
1485
|
+
|
|
1486
|
+
## \u641C\u7D22\u951A\u70B9
|
|
1487
|
+
${anchors}${sourceSnippet}${groupText}${screenshotNote}
|
|
1488
|
+
|
|
1489
|
+
## \u5468\u8FB9\u5185\u5BB9
|
|
1490
|
+
${surroundings.length ? surroundings.join("\n") : "- \u65E0\u53EF\u7528\u5468\u8FB9\u6458\u8981"}
|
|
1491
|
+
|
|
1492
|
+
## \u539F\u59CB\u7ED3\u6784\u5316\u6570\u636E
|
|
1493
|
+
\`\`\`json
|
|
1494
|
+
${JSON.stringify(context, null, 2)}
|
|
1495
|
+
\`\`\``;
|
|
1496
|
+
}
|
|
1497
|
+
function buildHtmlElementSelectionContext(input) {
|
|
1498
|
+
const limits = { truncated: false, omittedSensitiveFields: [] };
|
|
1499
|
+
const rawAttributes = input.selection.attributes ?? {};
|
|
1500
|
+
const attributes = sanitizeAttributes(rawAttributes, {
|
|
1501
|
+
get truncated() {
|
|
1502
|
+
return limits.truncated;
|
|
1503
|
+
},
|
|
1504
|
+
set truncated(value) {
|
|
1505
|
+
limits.truncated = value;
|
|
1506
|
+
},
|
|
1507
|
+
omittedSensitiveFields: limits.omittedSensitiveFields
|
|
1508
|
+
});
|
|
1509
|
+
const visibleText = input.selection.visibleText ? truncate2(input.selection.visibleText.replace(/\s+/g, " ").trim(), TEXT_LIMIT, limits) : void 0;
|
|
1510
|
+
const accessibleName = input.selection.accessibleName ? truncate2(input.selection.accessibleName.replace(/\s+/g, " ").trim(), TEXT_LIMIT, limits) : void 0;
|
|
1511
|
+
const html = input.html ?? "";
|
|
1512
|
+
const sourceKind = input.sourceKind ?? "html_file";
|
|
1513
|
+
const source = html ? locateHtmlElementSource(html, {
|
|
1514
|
+
tag: input.selection.tag,
|
|
1515
|
+
attributes,
|
|
1516
|
+
visibleText: visibleText || accessibleName
|
|
1517
|
+
}) : {
|
|
1518
|
+
searchAnchors: visibleText ? [`text="${visibleText}"`] : [],
|
|
1519
|
+
locatorConfidence: "low",
|
|
1520
|
+
reason: sourceKind === "running_page" ? "\u8FD0\u884C\u9875\u9762\u672A\u63D0\u4F9B\u6E90 HTML\uFF0C\u9700\u7ED3\u5408\u524D\u7AEF\u6E90\u7801\u548C\u8DEF\u7531\u4EBA\u5DE5\u6838\u5BF9" : "\u672A\u63D0\u4F9B\u6E90 HTML\uFF0C\u9700\u7ED3\u5408\u6587\u4EF6\u5185\u5BB9\u4EBA\u5DE5\u6838\u5BF9"
|
|
1521
|
+
};
|
|
1522
|
+
const viewport = input.selection.viewport ?? {
|
|
1523
|
+
width: 0,
|
|
1524
|
+
height: 0,
|
|
1525
|
+
devicePixelRatio: 1
|
|
1526
|
+
};
|
|
1527
|
+
const groupItems = sanitizeGroupItems(input.selection, limits);
|
|
1528
|
+
const groupLabel = input.selection.selectionMode === "group" ? input.selection.groupLabel || `\u7EC4\u5408\u9009\u533A\uFF08${input.selection.groupCount || groupItems?.length || 0} \u4E2A\u5185\u5BB9\uFF09` : void 0;
|
|
1529
|
+
const elementLabel = groupLabel ? `\u7EC4\u5408\u533A\u57DF\u300C${groupLabel}\u300D` : humanElementLabel({ ...input.selection, visibleText, accessibleName });
|
|
1530
|
+
const context = {
|
|
1531
|
+
schema: "blade.html_element_selection.v1",
|
|
1532
|
+
selected_at: input.selectedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1533
|
+
source_kind: sourceKind,
|
|
1534
|
+
file: {
|
|
1535
|
+
path: input.filePath,
|
|
1536
|
+
name: fileNameFromPath(input.filePath, input.fileName),
|
|
1537
|
+
language: "html",
|
|
1538
|
+
content_hash: simpleContentHash(html || input.pageUrl || input.filePath)
|
|
1539
|
+
},
|
|
1540
|
+
preview: {
|
|
1541
|
+
mode: sourceKind === "running_page" ? "running_page" : "render",
|
|
1542
|
+
title: input.title,
|
|
1543
|
+
url: input.pageUrl,
|
|
1544
|
+
viewport: {
|
|
1545
|
+
width: viewport.width,
|
|
1546
|
+
height: viewport.height,
|
|
1547
|
+
device_pixel_ratio: viewport.devicePixelRatio
|
|
1548
|
+
}
|
|
1549
|
+
},
|
|
1550
|
+
element: {
|
|
1551
|
+
label: elementLabel,
|
|
1552
|
+
tag: input.selection.tag.toLowerCase(),
|
|
1553
|
+
role: input.selection.role,
|
|
1554
|
+
accessible_name: accessibleName,
|
|
1555
|
+
visible_text: visibleText,
|
|
1556
|
+
attributes,
|
|
1557
|
+
selectors: mergeSelectors(input.selection, attributes),
|
|
1558
|
+
dom_path: input.selection.domPath,
|
|
1559
|
+
rect: input.selection.rect,
|
|
1560
|
+
style: sanitizeStyle(input.selection.style ?? {}, limits)
|
|
1561
|
+
},
|
|
1562
|
+
group: groupItems?.length ? {
|
|
1563
|
+
label: groupLabel || `\u7EC4\u5408\u9009\u533A\uFF08${groupItems.length} \u4E2A\u5185\u5BB9\uFF09`,
|
|
1564
|
+
count: input.selection.groupCount || groupItems.length,
|
|
1565
|
+
items: groupItems
|
|
1566
|
+
} : void 0,
|
|
1567
|
+
source: sourceToContext(source),
|
|
1568
|
+
screenshot: input.selection.screenshotDataUrl ? {
|
|
1569
|
+
included: true,
|
|
1570
|
+
note: "\u5DF2\u9644\u52A0\u9009\u4E2D\u5143\u7D20\u622A\u56FE\uFF1B\u975E\u591A\u6A21\u6001\u6A21\u578B\u4F1A\u81EA\u52A8\u5FFD\u7565\u56FE\u7247\uFF0C\u8BF7\u4F18\u5148\u4F7F\u7528\u6587\u672C\u4E0A\u4E0B\u6587\u3002"
|
|
1571
|
+
} : input.selection.screenshotStatus === "failed" ? {
|
|
1572
|
+
included: false,
|
|
1573
|
+
note: "\u622A\u56FE\u751F\u6210\u5931\u8D25\uFF1B\u5DF2\u4FDD\u7559\u6587\u672C\u4E0A\u4E0B\u6587\u4F9B\u6A21\u578B\u5B9A\u4F4D\u3002",
|
|
1574
|
+
reason: input.selection.screenshotError
|
|
1575
|
+
} : void 0,
|
|
1576
|
+
surroundings: {
|
|
1577
|
+
parent_summary: input.selection.surroundings?.parentSummary,
|
|
1578
|
+
children_summary: limitList(input.selection.surroundings?.childrenSummary, limits),
|
|
1579
|
+
previous_siblings: limitList(input.selection.surroundings?.previousSiblings, limits),
|
|
1580
|
+
next_siblings: limitList(input.selection.surroundings?.nextSiblings, limits)
|
|
1581
|
+
},
|
|
1582
|
+
limits: {
|
|
1583
|
+
truncated: limits.truncated || Boolean(source.snippet?.endsWith("\u2026")),
|
|
1584
|
+
omitted_sensitive_fields: limits.omittedSensitiveFields
|
|
1585
|
+
}
|
|
1586
|
+
};
|
|
1587
|
+
return {
|
|
1588
|
+
label: `HTML \u9009\u4E2D\u9879\uFF1A${context.element.label}`,
|
|
1589
|
+
content: contextMarkdown(context),
|
|
1590
|
+
context,
|
|
1591
|
+
imageUrl: input.selection.screenshotDataUrl
|
|
1592
|
+
};
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1135
1595
|
// src/react/schemas/session.ts
|
|
1136
1596
|
import { type } from "arktype";
|
|
1137
1597
|
var SessionStatus = type(
|
|
@@ -1173,6 +1633,7 @@ var LayoutType = /* @__PURE__ */ ((LayoutType2) => {
|
|
|
1173
1633
|
LayoutType2["BladeCoa"] = "blade-coa";
|
|
1174
1634
|
LayoutType2["ChatPreview"] = "chat-preview";
|
|
1175
1635
|
LayoutType2["ChatOnly"] = "chat-only";
|
|
1636
|
+
LayoutType2["SolutionApp"] = "solution-app";
|
|
1176
1637
|
return LayoutType2;
|
|
1177
1638
|
})(LayoutType || {});
|
|
1178
1639
|
|
|
@@ -1394,6 +1855,7 @@ export {
|
|
|
1394
1855
|
attachHostBridgeListener,
|
|
1395
1856
|
auth_exports as authApi,
|
|
1396
1857
|
bootstrapBladeClient,
|
|
1858
|
+
buildHtmlElementSelectionContext,
|
|
1397
1859
|
buildMessageContent,
|
|
1398
1860
|
buildSessionBinaryPreviewTarget,
|
|
1399
1861
|
buildStepRanges,
|
|
@@ -1420,6 +1882,7 @@ export {
|
|
|
1420
1882
|
isUiMeta,
|
|
1421
1883
|
knowledgeApi,
|
|
1422
1884
|
listSkillOrgs,
|
|
1885
|
+
locateHtmlElementSource,
|
|
1423
1886
|
memories_exports as memoriesApi,
|
|
1424
1887
|
models_exports as modelsApi,
|
|
1425
1888
|
normalizeCodeLanguage,
|