@cydm/pie 1.0.51 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -15
- package/dist/builtin/extensions/ask-user/index.js +4 -3
- package/dist/builtin/extensions/ask-user/package.json +8 -7
- package/dist/builtin/extensions/changelog/package.json +9 -9
- package/dist/builtin/extensions/computer-use/index.js +5466 -0
- package/dist/builtin/extensions/computer-use/package.json +11 -0
- package/dist/builtin/extensions/computer-use/prebuilt/linux/arm64/linux-bridge +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/linux/x64/linux-bridge +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/arm64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/Info.plist +24 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/_CodeSignature/CodeResources +115 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/x64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/windows/windows-bridge.exe +0 -0
- package/dist/builtin/extensions/computer-use/scripts/build-native.mjs +277 -0
- package/dist/builtin/extensions/computer-use/scripts/helper-path.mjs +48 -0
- package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +549 -0
- package/dist/builtin/extensions/document-attachments/package.json +9 -9
- package/dist/builtin/extensions/init/package.json +9 -9
- package/dist/builtin/extensions/mcp-adapter/index.js +25250 -0
- package/dist/builtin/extensions/mcp-adapter/package.json +11 -0
- package/dist/builtin/extensions/plan-mode/index.js +4 -3
- package/dist/builtin/extensions/plan-mode/package.json +9 -9
- package/dist/builtin/extensions/subagent/index.js +6 -4
- package/dist/builtin/extensions/subagent/package.json +16 -12
- package/dist/builtin/extensions/todo/index.js +4 -3
- package/dist/builtin/extensions/todo/package.json +9 -9
- package/dist/builtin/skills/chrome-devtools-axi/CHANGELOG.md +5 -0
- package/dist/builtin/skills/chrome-devtools-axi/README.md +17 -0
- package/dist/builtin/skills/chrome-devtools-axi/SKILL.md +31 -0
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-cli.js +77 -0
- package/dist/builtin/skills/chrome-devtools-axi/package.json +12 -0
- package/dist/builtin/skills/tui-use/README.md +7 -0
- package/dist/builtin/skills/tui-use/SKILL.md +58 -0
- package/dist/chunks/chunk-5353DEEC.js +130 -0
- package/dist/chunks/{chunk-KDPAGHYY.js → chunk-G2POWIA5.js} +129 -194
- package/dist/chunks/{chunk-S2J3SZZX.js → chunk-IM43UYVV.js} +827 -3385
- package/dist/chunks/{chunk-A644H2XX.js → chunk-PMPD56N2.js} +159 -72
- package/dist/chunks/{chunk-B3SMW2XW.js → chunk-QJH6YN2W.js} +1 -1
- package/dist/chunks/chunk-XXGYUYXI.js +2718 -0
- package/dist/chunks/{src-UKCIAX6F.js → src-QSP2OPHU.js} +3 -2
- package/dist/chunks/{test-stream-NCBFPM2I.js → test-stream-CVGWFLSX.js} +2 -1
- package/dist/chunks/webapi-MBCKO7ZV.js +2481 -0
- package/dist/cli.js +149 -68
- package/package.json +5 -4
- package/dist/builtin/skills/browser-tools/CHANGELOG.md +0 -5
- package/dist/builtin/skills/browser-tools/README.md +0 -17
- package/dist/builtin/skills/browser-tools/SKILL.md +0 -43
- package/dist/builtin/skills/browser-tools/package.json +0 -12
- package/dist/builtin/skills/browser-tools/playwright-cli.js +0 -45
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
Agent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QJH6YN2W.js";
|
|
5
5
|
import {
|
|
6
6
|
FileSystemGateway,
|
|
7
|
-
Type,
|
|
8
7
|
completeSimple,
|
|
9
8
|
detectPlatform,
|
|
10
9
|
getFileSystem,
|
|
11
10
|
getPlatformConfig,
|
|
12
11
|
hashText,
|
|
13
12
|
streamSimple
|
|
14
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-IM43UYVV.js";
|
|
14
|
+
import {
|
|
15
|
+
Type
|
|
16
|
+
} from "./chunk-XXGYUYXI.js";
|
|
15
17
|
import {
|
|
16
18
|
__commonJS,
|
|
17
19
|
__toESM
|
|
@@ -6254,7 +6256,10 @@ async function askSingleQuestion(args) {
|
|
|
6254
6256
|
if (response.type === "multiline_input" && (response.skipped || response.timedOut)) {
|
|
6255
6257
|
return buildSkippedResult(question, response.timedOut === true);
|
|
6256
6258
|
}
|
|
6257
|
-
const answer = response.type === "multiline_input" ? response.value : void 0;
|
|
6259
|
+
const answer = response.type === "multiline_input" ? response.value?.trim() : void 0;
|
|
6260
|
+
if (answer === "") {
|
|
6261
|
+
return buildSkippedResult(question, false);
|
|
6262
|
+
}
|
|
6258
6263
|
if (answer === void 0) {
|
|
6259
6264
|
return { content: [{ type: "text", text: "User cancelled" }], details: { cancelled: true } };
|
|
6260
6265
|
}
|
|
@@ -6272,7 +6277,12 @@ async function askSingleQuestion(args) {
|
|
|
6272
6277
|
id: `ask-user:select:${Date.now()}`,
|
|
6273
6278
|
prompt: question,
|
|
6274
6279
|
options: displayOptions,
|
|
6275
|
-
timeoutMs: DEFAULT_ASK_TIMEOUT_MS
|
|
6280
|
+
timeoutMs: DEFAULT_ASK_TIMEOUT_MS,
|
|
6281
|
+
// Tab-style navigation for hosts that support it: ← at the first page
|
|
6282
|
+
// selects Back, → at the last page selects Review (row presence mirrors
|
|
6283
|
+
// allowBack/allowReview). Hosts without shortcut support ignore these.
|
|
6284
|
+
leftShortcut: allowBack ? BACK_OPTION : void 0,
|
|
6285
|
+
rightShortcut: allowReview ? REVIEW_OPTION : void 0
|
|
6276
6286
|
});
|
|
6277
6287
|
if (selection.type === "select_one" && (selection.skipped || selection.timedOut)) {
|
|
6278
6288
|
return buildSkippedResult(question, selection.timedOut === true);
|
|
@@ -6297,7 +6307,10 @@ async function askSingleQuestion(args) {
|
|
|
6297
6307
|
if (response.type === "text_input" && (response.skipped || response.timedOut)) {
|
|
6298
6308
|
return buildSkippedResult(question, response.timedOut === true);
|
|
6299
6309
|
}
|
|
6300
|
-
const customAnswer = response.type === "text_input" ? response.value : void 0;
|
|
6310
|
+
const customAnswer = response.type === "text_input" ? response.value?.trim() : void 0;
|
|
6311
|
+
if (customAnswer === "") {
|
|
6312
|
+
return buildSkippedResult(question, false);
|
|
6313
|
+
}
|
|
6301
6314
|
if (customAnswer === void 0) {
|
|
6302
6315
|
return { content: [{ type: "text", text: "User cancelled" }], details: { cancelled: true } };
|
|
6303
6316
|
}
|
|
@@ -6377,8 +6390,11 @@ function createAskUserCapability() {
|
|
|
6377
6390
|
}
|
|
6378
6391
|
answers[q.id] = {
|
|
6379
6392
|
question: q.question,
|
|
6380
|
-
|
|
6381
|
-
|
|
6393
|
+
...result.details,
|
|
6394
|
+
// After the spread: `answer` wins over the same spread key, and
|
|
6395
|
+
// `??` preserves intentional values (`||` let "" re-clobber the
|
|
6396
|
+
// fallback — a latent trap for any falsy answer).
|
|
6397
|
+
answer: result.details?.answer ?? result.content[0].text
|
|
6382
6398
|
};
|
|
6383
6399
|
currentIndex++;
|
|
6384
6400
|
}
|
|
@@ -6387,7 +6403,7 @@ function createAskUserCapability() {
|
|
|
6387
6403
|
const reviewOptions = [
|
|
6388
6404
|
CONFIRM_OPTION,
|
|
6389
6405
|
...questions.map((q2, i) => {
|
|
6390
|
-
const answer = answers[q2.id]?.answer
|
|
6406
|
+
const answer = answers[q2.id]?.answer ?? "(not answered)";
|
|
6391
6407
|
const displayAnswer = answer.length > 20 ? `${answer.substring(0, 20)}...` : answer;
|
|
6392
6408
|
return `\u270F\uFE0F Q${i + 1}: ${displayAnswer}`;
|
|
6393
6409
|
}),
|
|
@@ -6441,8 +6457,8 @@ function createAskUserCapability() {
|
|
|
6441
6457
|
}
|
|
6442
6458
|
answers[q.id] = {
|
|
6443
6459
|
question: q.question,
|
|
6444
|
-
|
|
6445
|
-
|
|
6460
|
+
...result.details,
|
|
6461
|
+
answer: result.details?.answer ?? result.content[0].text
|
|
6446
6462
|
};
|
|
6447
6463
|
}
|
|
6448
6464
|
}
|
|
@@ -11651,6 +11667,13 @@ function getModelLabel(model) {
|
|
|
11651
11667
|
function textFromAssistant(message) {
|
|
11652
11668
|
return message.content.filter((block) => block.type === "text").map((block) => block.text).join("\n").trim();
|
|
11653
11669
|
}
|
|
11670
|
+
function classifyUnderstandingFailure(message) {
|
|
11671
|
+
if (/\b40[123]\b|payment required|insufficient[ _-]?balance|arrearage|余额|quota/i.test(message)) return "auth_or_balance";
|
|
11672
|
+
if (/\b429\b|rate.?limit|too many requests/i.test(message)) return "rate_limited";
|
|
11673
|
+
if (/timed? ?out|timeout|etimedout/i.test(message)) return "timeout";
|
|
11674
|
+
if (/does not support|unsupported|multimodal|modality|not declare/i.test(message)) return "unsupported";
|
|
11675
|
+
return "provider_error";
|
|
11676
|
+
}
|
|
11654
11677
|
function modalityForReadFileUnderstandingKind(kind) {
|
|
11655
11678
|
if (kind === "image") return "image";
|
|
11656
11679
|
if (kind === "video") return "video";
|
|
@@ -11683,83 +11706,147 @@ function createReadFileUnderstandingHandler(deps) {
|
|
|
11683
11706
|
}
|
|
11684
11707
|
async function understandFileWithModel(deps, request) {
|
|
11685
11708
|
const purpose = `read_file.${request.kind}`;
|
|
11686
|
-
const decision = deps.resolveToolModel(purpose);
|
|
11687
11709
|
const agentModel = deps.getAgentModel();
|
|
11688
|
-
const
|
|
11710
|
+
const singleDecision = deps.resolveToolModel(purpose);
|
|
11711
|
+
const candidateDecisions = deps.resolveToolModelCandidates?.(purpose) ?? [singleDecision];
|
|
11712
|
+
const sessionId = deps.getSessionId() || `read-file-${Date.now()}`;
|
|
11713
|
+
const attempts = [];
|
|
11714
|
+
let sendAttemptCount = 0;
|
|
11715
|
+
const baseRouteDetails = {
|
|
11689
11716
|
purpose,
|
|
11690
|
-
requiredCapability:
|
|
11691
|
-
routeSource: decision.routeSource,
|
|
11717
|
+
requiredCapability: singleDecision.requiredCapability,
|
|
11692
11718
|
agentModel: getModelLabel(agentModel),
|
|
11693
|
-
toolModel: getModelLabel(decision.model),
|
|
11694
|
-
fallbackReason: decision.fallbackReason,
|
|
11695
11719
|
kind: request.kind,
|
|
11696
11720
|
mimeType: request.mimeType
|
|
11697
11721
|
};
|
|
11698
|
-
|
|
11722
|
+
for (const decision of candidateDecisions) {
|
|
11723
|
+
const attemptBase = { toolModel: getModelLabel(decision.model), routeSource: decision.routeSource };
|
|
11724
|
+
if (!decision.model || !decision.apiKey) {
|
|
11725
|
+
attempts.push({
|
|
11726
|
+
...attemptBase,
|
|
11727
|
+
failureCategory: "unavailable",
|
|
11728
|
+
fallbackReason: decision.fallbackReason,
|
|
11729
|
+
durationMs: 0
|
|
11730
|
+
});
|
|
11731
|
+
continue;
|
|
11732
|
+
}
|
|
11733
|
+
const startedAt = Date.now();
|
|
11734
|
+
sendAttemptCount += 1;
|
|
11735
|
+
try {
|
|
11736
|
+
const directImageContent = buildDirectImageUnderstandingContent(request);
|
|
11737
|
+
const prepared = directImageContent ? { content: directImageContent, details: { inputMode: "inlineDataUrl" } } : await deps.prepareFileContent({
|
|
11738
|
+
request,
|
|
11739
|
+
model: decision.model,
|
|
11740
|
+
apiKey: decision.apiKey,
|
|
11741
|
+
sessionId
|
|
11742
|
+
});
|
|
11743
|
+
const send = deps.sendUnderstandingRequest ?? completeSimple;
|
|
11744
|
+
const response = await send(
|
|
11745
|
+
decision.model,
|
|
11746
|
+
{
|
|
11747
|
+
systemPrompt: "You are a file-understanding tool. Answer only from the provided file. Keep the answer concise and factual.",
|
|
11748
|
+
messages: [{ role: "user", content: [buildReadFileUnderstandingPrompt(request), ...prepared.content], timestamp: Date.now() }]
|
|
11749
|
+
},
|
|
11750
|
+
{
|
|
11751
|
+
apiKey: decision.apiKey,
|
|
11752
|
+
maxTokens: Math.min(decision.model.maxTokens || 4096, 4096),
|
|
11753
|
+
signal: request.signal
|
|
11754
|
+
}
|
|
11755
|
+
);
|
|
11756
|
+
const errorMessage = response.stopReason === "error" || response.stopReason === "aborted" ? response.errorMessage : void 0;
|
|
11757
|
+
const durationMs = Date.now() - startedAt;
|
|
11758
|
+
if (response.stopReason === "aborted") {
|
|
11759
|
+
attempts.push({ ...attemptBase, failureCategory: "aborted", error: errorMessage, durationMs });
|
|
11760
|
+
return {
|
|
11761
|
+
content: [{ type: "text", text: `read_file ${request.kind} understanding failed: ${errorMessage ?? "aborted"}` }],
|
|
11762
|
+
details: { understanding: { ...baseRouteDetails, ...attemptBase, error: errorMessage, attempts } },
|
|
11763
|
+
isError: true
|
|
11764
|
+
};
|
|
11765
|
+
}
|
|
11766
|
+
if (errorMessage) {
|
|
11767
|
+
attempts.push({
|
|
11768
|
+
...attemptBase,
|
|
11769
|
+
failureCategory: classifyUnderstandingFailure(errorMessage),
|
|
11770
|
+
error: errorMessage,
|
|
11771
|
+
durationMs
|
|
11772
|
+
});
|
|
11773
|
+
continue;
|
|
11774
|
+
}
|
|
11775
|
+
attempts.push({ ...attemptBase, durationMs });
|
|
11776
|
+
const text = textFromAssistant(response) || "(file understanding model returned no text)";
|
|
11777
|
+
return {
|
|
11778
|
+
content: [{ type: "text", text }],
|
|
11779
|
+
details: {
|
|
11780
|
+
understanding: {
|
|
11781
|
+
...baseRouteDetails,
|
|
11782
|
+
// Capability follows the candidate that actually served the request,
|
|
11783
|
+
// not the first decision's.
|
|
11784
|
+
requiredCapability: decision.requiredCapability,
|
|
11785
|
+
...attemptBase,
|
|
11786
|
+
fallbackReason: decision.fallbackReason,
|
|
11787
|
+
responseStopReason: response.stopReason,
|
|
11788
|
+
...prepared.details,
|
|
11789
|
+
attempts
|
|
11790
|
+
}
|
|
11791
|
+
},
|
|
11792
|
+
isError: false
|
|
11793
|
+
};
|
|
11794
|
+
} catch (error) {
|
|
11795
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
11796
|
+
const durationMs = Date.now() - startedAt;
|
|
11797
|
+
if (request.signal?.aborted) {
|
|
11798
|
+
attempts.push({ ...attemptBase, failureCategory: "aborted", error: message, durationMs });
|
|
11799
|
+
return {
|
|
11800
|
+
content: [{ type: "text", text: `read_file ${request.kind} understanding failed: ${message}` }],
|
|
11801
|
+
details: { understanding: { ...baseRouteDetails, ...attemptBase, error: message, attempts } },
|
|
11802
|
+
isError: true
|
|
11803
|
+
};
|
|
11804
|
+
}
|
|
11805
|
+
attempts.push({
|
|
11806
|
+
...attemptBase,
|
|
11807
|
+
failureCategory: classifyUnderstandingFailure(message),
|
|
11808
|
+
error: message,
|
|
11809
|
+
durationMs
|
|
11810
|
+
});
|
|
11811
|
+
}
|
|
11812
|
+
}
|
|
11813
|
+
const routedAttempts = attempts.filter((attempt) => attempt.toolModel !== void 0);
|
|
11814
|
+
if (routedAttempts.length === 0 || sendAttemptCount === 0) {
|
|
11699
11815
|
return {
|
|
11700
11816
|
content: [{
|
|
11701
11817
|
type: "text",
|
|
11702
|
-
text:
|
|
11818
|
+
text: singleDecision.fallbackReason || `No configured model declares ${request.kind} capability for ${purpose}.`
|
|
11703
11819
|
}],
|
|
11704
|
-
details: { understanding: routeDetails },
|
|
11705
|
-
isError: true
|
|
11706
|
-
};
|
|
11707
|
-
}
|
|
11708
|
-
const sessionId = deps.getSessionId() || `read-file-${Date.now()}`;
|
|
11709
|
-
try {
|
|
11710
|
-
const directImageContent = buildDirectImageUnderstandingContent(request);
|
|
11711
|
-
const prepared = directImageContent ? { content: directImageContent, details: { inputMode: "inlineDataUrl" } } : await deps.prepareFileContent({
|
|
11712
|
-
request,
|
|
11713
|
-
model: decision.model,
|
|
11714
|
-
apiKey: decision.apiKey,
|
|
11715
|
-
sessionId
|
|
11716
|
-
});
|
|
11717
|
-
const fileContent = prepared.content;
|
|
11718
|
-
const content = [
|
|
11719
|
-
buildReadFileUnderstandingPrompt(request),
|
|
11720
|
-
...fileContent
|
|
11721
|
-
];
|
|
11722
|
-
const response = await completeSimple(
|
|
11723
|
-
decision.model,
|
|
11724
|
-
{
|
|
11725
|
-
systemPrompt: "You are a file-understanding tool. Answer only from the provided file. Keep the answer concise and factual.",
|
|
11726
|
-
messages: [{ role: "user", content, timestamp: Date.now() }]
|
|
11727
|
-
},
|
|
11728
|
-
{
|
|
11729
|
-
apiKey: decision.apiKey,
|
|
11730
|
-
maxTokens: Math.min(decision.model.maxTokens || 4096, 4096),
|
|
11731
|
-
signal: request.signal
|
|
11732
|
-
}
|
|
11733
|
-
);
|
|
11734
|
-
const errorMessage = response.stopReason === "error" || response.stopReason === "aborted" ? response.errorMessage : void 0;
|
|
11735
|
-
const text = textFromAssistant(response) || (errorMessage ? `read_file ${request.kind} understanding failed: ${errorMessage}` : "(file understanding model returned no text)");
|
|
11736
|
-
return {
|
|
11737
|
-
content: [{ type: "text", text }],
|
|
11738
|
-
details: {
|
|
11739
|
-
understanding: {
|
|
11740
|
-
...routeDetails,
|
|
11741
|
-
toolModel: getModelLabel(decision.model),
|
|
11742
|
-
responseStopReason: response.stopReason,
|
|
11743
|
-
...prepared.details,
|
|
11744
|
-
...errorMessage ? { error: errorMessage } : {}
|
|
11745
|
-
}
|
|
11746
|
-
},
|
|
11747
|
-
isError: response.stopReason === "error" || response.stopReason === "aborted"
|
|
11748
|
-
};
|
|
11749
|
-
} catch (error) {
|
|
11750
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
11751
|
-
return {
|
|
11752
|
-
content: [{ type: "text", text: `read_file ${request.kind} understanding failed: ${message}` }],
|
|
11753
11820
|
details: {
|
|
11754
11821
|
understanding: {
|
|
11755
|
-
...
|
|
11756
|
-
toolModel: getModelLabel(
|
|
11757
|
-
|
|
11822
|
+
...baseRouteDetails,
|
|
11823
|
+
toolModel: getModelLabel(singleDecision.model),
|
|
11824
|
+
routeSource: singleDecision.routeSource,
|
|
11825
|
+
fallbackReason: singleDecision.fallbackReason,
|
|
11826
|
+
attempts
|
|
11758
11827
|
}
|
|
11759
11828
|
},
|
|
11760
11829
|
isError: true
|
|
11761
11830
|
};
|
|
11762
11831
|
}
|
|
11832
|
+
const lastAttempt = routedAttempts[routedAttempts.length - 1];
|
|
11833
|
+
const viaSegments = attempts.filter((attempt) => attempt.error || attempt.fallbackReason).map((attempt) => `via ${attempt.toolModel ?? "unconfigured route"}: ${attempt.error ?? attempt.fallbackReason}`);
|
|
11834
|
+
const firstFailure = attempts.find((attempt) => attempt.error || attempt.fallbackReason);
|
|
11835
|
+
const combinedError = sendAttemptCount === 1 ? `read_file ${request.kind} understanding failed: ${firstFailure?.error ?? firstFailure?.fallbackReason ?? "unknown error"}` : `read_file ${request.kind} understanding failed after ${sendAttemptCount} route(s): ${viaSegments.join("; ")}`;
|
|
11836
|
+
return {
|
|
11837
|
+
content: [{ type: "text", text: combinedError }],
|
|
11838
|
+
details: {
|
|
11839
|
+
understanding: {
|
|
11840
|
+
...baseRouteDetails,
|
|
11841
|
+
toolModel: lastAttempt.toolModel,
|
|
11842
|
+
routeSource: lastAttempt.routeSource,
|
|
11843
|
+
fallbackReason: lastAttempt.fallbackReason ?? lastAttempt.error,
|
|
11844
|
+
error: combinedError,
|
|
11845
|
+
attempts
|
|
11846
|
+
}
|
|
11847
|
+
},
|
|
11848
|
+
isError: true
|
|
11849
|
+
};
|
|
11763
11850
|
}
|
|
11764
11851
|
|
|
11765
11852
|
// ../../packages/shared-headless-capabilities/src/session-trace.ts
|
|
@@ -13859,7 +13946,7 @@ function createSharedWebFetchTool(deps = {}) {
|
|
|
13859
13946
|
const extractionMethod = isHtml ? "html_readability" : isPdf ? "pdf_text" : "plain_text";
|
|
13860
13947
|
if (isHtml && looksJavaScriptHeavy(raw, text)) {
|
|
13861
13948
|
return {
|
|
13862
|
-
content: [{ type: "text", text: `web_fetch could not read meaningful content from ${url}; this page appears to require JavaScript. Use
|
|
13949
|
+
content: [{ type: "text", text: `web_fetch could not read meaningful content from ${url}; this page appears to require JavaScript. Use the chrome-devtools-axi skill (or computer-use browser tools) for browser-rendered content.` }],
|
|
13863
13950
|
details: {
|
|
13864
13951
|
url,
|
|
13865
13952
|
sourceUrl: url,
|