surf-cli 2.11.0 → 2.13.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 +39 -0
- package/native/cli.cjs +66 -4
- package/native/host-helpers.cjs +45 -2
- package/native/host-sessions.cjs +1 -0
- package/native/host.cjs +110 -6
- package/native/kimi-client.cjs +912 -0
- package/native/mcp-server.cjs +10 -0
- package/native/playbook-cli.cjs +3 -2
- package/native/playbook-runtime.cjs +29 -2
- package/native/playbooks.cjs +13 -0
- package/native/workflow-definition.cjs +1 -0
- package/native/workflow-script-runtime.cjs +294 -0
- package/package.json +20 -5
- package/pi-extension/surf.ts +292 -0
- package/skills/README.md +6 -0
- package/skills/surf/SKILL.md +24 -6
package/README.md
CHANGED
|
@@ -230,9 +230,14 @@ surf read --compact # Remove empty structural elements
|
|
|
230
230
|
surf read --depth 3 --compact # Both (60% smaller output)
|
|
231
231
|
surf read --max-bytes 2000 # Cap visible text on a UTF-8 byte boundary
|
|
232
232
|
surf page.text # Raw text content only
|
|
233
|
+
surf page.html # Rendered document HTML
|
|
234
|
+
surf page.html --strip-scripts > artifact.html # Save a safe static Claude artifact
|
|
235
|
+
surf page.save --selector "#artifact" --strip-scripts --output artifact.html # Save one rendered element
|
|
233
236
|
surf page.state # Modals, loading state, scroll position
|
|
234
237
|
```
|
|
235
238
|
|
|
239
|
+
Use `surf page.html --strip-scripts` after the page loads when you need a static export of a Claude artifact or other rendered DOM. Use `--selector <css>` to export one element. Both commands target the active frame when `frame.switch` is active.
|
|
240
|
+
|
|
236
241
|
Element refs (`e1`, `e2`, `e3`...) are stable identifiers from the accessibility tree - semantic, predictable, and resilient to DOM changes.
|
|
237
242
|
|
|
238
243
|
### Semantic Locators
|
|
@@ -485,6 +490,12 @@ surf aistudio "explain quantum computing"
|
|
|
485
490
|
surf aistudio "redteam this" --with-page # Include page context
|
|
486
491
|
surf aistudio "quick answer" --model gemini-3-flash-preview # Model selection
|
|
487
492
|
|
|
493
|
+
# Kimi (queries kimi.com - Moonshot K-series - using your browser login)
|
|
494
|
+
surf kimi "explain quantum computing"
|
|
495
|
+
surf kimi "summarize" --with-page # Include page context
|
|
496
|
+
surf kimi "quick answer" --model thinking # Models: instant (default), thinking, high
|
|
497
|
+
surf kimi --validate # Check kimi.com UI and available models
|
|
498
|
+
|
|
488
499
|
# AI Studio App Builder (generates full web apps from a prompt)
|
|
489
500
|
surf aistudio.build "build a portfolio site"
|
|
490
501
|
surf aistudio.build "todo app" --model gemini-3.1-pro-preview # Model override
|
|
@@ -707,6 +718,21 @@ surf use page read --json
|
|
|
707
718
|
surf use <site> <write-op> --write --resource-id 123
|
|
708
719
|
```
|
|
709
720
|
|
|
721
|
+
Playbook read ops can also use a trusted `script` strategy when fixed JSON steps are too rigid. Scripts require `--allow-script` at run time. Only run scripts from playbooks you trust. This is not a security sandbox.
|
|
722
|
+
|
|
723
|
+
The script gets `input`, `tools.run`, `tools.all`, `tools.ref`/`refs`, `emit`, and `console`. Tool calls still use Surf workflow step behavior, including auto-waits unless `autoWait` is `false`.
|
|
724
|
+
|
|
725
|
+
```json
|
|
726
|
+
{
|
|
727
|
+
"using": "script",
|
|
728
|
+
"script": [
|
|
729
|
+
"const page = await tools.run('page', { tool: 'page.text', args: {} });",
|
|
730
|
+
"const clicked = await tools.all(input.selectors.map((selector) => ({ key: selector.slice(1), tool: 'click', args: { selector } })));",
|
|
731
|
+
"return { page: page.output, clicked: clicked.map((link) => link.output) };"
|
|
732
|
+
]
|
|
733
|
+
}
|
|
734
|
+
```
|
|
735
|
+
|
|
710
736
|
Project playbooks in `./.surf/playbooks/` override user playbooks in `~/.surf/playbooks/`; built-ins are the final fallback. `show` reports the selected source. Provider compatibility commands continue to use their validated command paths until provider playbooks have real login-flow validation.
|
|
711
737
|
|
|
712
738
|
Author a playbook from redacted recent activity or an explicit evidence record:
|
|
@@ -932,6 +958,19 @@ cp -r skills/surf ~/.pi/agent/skills/
|
|
|
932
958
|
|
|
933
959
|
See [`skills/README.md`](skills/README.md) for details.
|
|
934
960
|
|
|
961
|
+
### Pi extension
|
|
962
|
+
|
|
963
|
+
Surf also includes an optional Pi extension. Install or load Surf as a Pi package, or load it from a checkout:
|
|
964
|
+
|
|
965
|
+
```bash
|
|
966
|
+
pi install npm:surf-cli
|
|
967
|
+
pi -e /path/to/surf-cli/pi-extension/surf.ts
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
It registers `surf_read`, `surf_screenshot`, `surf_click`, `surf_type`, `surf_tool`, and the `surf_oracle_*` tools. Browser calls use Surf's native-host socket, not shell commands. If `pi-subagents/background-work` is installed, the extension also reports active oracle jobs started by that Pi session. Pi still loads the browser tools when pi-subagents is not installed.
|
|
971
|
+
|
|
972
|
+
Surf agents share one browser session. Use read tools for parallel scouts when possible. `surf_click` and `surf_type` can interfere with another agent's browser actions. Browser leases are not available yet.
|
|
973
|
+
|
|
935
974
|
## Development
|
|
936
975
|
|
|
937
976
|
```bash
|
package/native/cli.cjs
CHANGED
|
@@ -355,6 +355,22 @@ const TOOLS = {
|
|
|
355
355
|
{ cmd: 'aistudio "quick answer" --model gemini-3-flash-preview', desc: "Model selection" },
|
|
356
356
|
]
|
|
357
357
|
},
|
|
358
|
+
"kimi": {
|
|
359
|
+
desc: "Query Kimi AI (kimi.com, Moonshot K-series) using your browser session",
|
|
360
|
+
args: ["query"],
|
|
361
|
+
opts: {
|
|
362
|
+
"with-page": "Include current page context",
|
|
363
|
+
model: "Model: instant (default), thinking, high - or any model label shown in kimi.com's model picker",
|
|
364
|
+
timeout: "Timeout in seconds (default: 300)",
|
|
365
|
+
validate: "Check kimi.com UI and available models (no query sent)"
|
|
366
|
+
},
|
|
367
|
+
examples: [
|
|
368
|
+
{ cmd: 'kimi "explain quantum computing"', desc: "Basic query" },
|
|
369
|
+
{ cmd: 'kimi "summarize" --with-page', desc: "With page context" },
|
|
370
|
+
{ cmd: 'kimi "deep dive" --model thinking', desc: "Try the Thinking model" },
|
|
371
|
+
{ cmd: 'kimi --validate', desc: "Check UI and list available models" },
|
|
372
|
+
]
|
|
373
|
+
},
|
|
358
374
|
"aistudio.build": {
|
|
359
375
|
desc: "Build an app via Google AI Studio App Builder (uses browser session)",
|
|
360
376
|
args: ["query"],
|
|
@@ -533,7 +549,7 @@ const TOOLS = {
|
|
|
533
549
|
"scroll": {
|
|
534
550
|
desc: "Scroll in direction",
|
|
535
551
|
args: ["direction", "pixels"],
|
|
536
|
-
opts: { direction: "up|down|left|right", amount: "Scroll amount (1-10)" },
|
|
552
|
+
opts: { direction: "up|down|left|right", amount: "Scroll amount in 100 px steps (1-10)" },
|
|
537
553
|
examples: [
|
|
538
554
|
{ cmd: "scroll down 800", desc: "Scroll down 800px" },
|
|
539
555
|
{ cmd: "scroll --direction down --amount 3", desc: "Scroll down" },
|
|
@@ -576,6 +592,18 @@ const TOOLS = {
|
|
|
576
592
|
},
|
|
577
593
|
"read": { desc: "Alias for page.read", args: [], alias: "page.read" },
|
|
578
594
|
"page.text": { desc: "Extract all text from page", args: [] },
|
|
595
|
+
"page.html": {
|
|
596
|
+
desc: "Print rendered document HTML",
|
|
597
|
+
args: [],
|
|
598
|
+
opts: { selector: "Export matching CSS selector", "strip-scripts": "Remove script elements" },
|
|
599
|
+
examples: [{ cmd: "page.html", desc: "Print current document HTML" }],
|
|
600
|
+
},
|
|
601
|
+
"page.save": {
|
|
602
|
+
desc: "Save rendered document HTML",
|
|
603
|
+
args: [],
|
|
604
|
+
opts: { output: "File path", selector: "Export matching CSS selector", "strip-scripts": "Remove script elements" },
|
|
605
|
+
examples: [{ cmd: "page.save --output page.html", desc: "Save current document HTML" }],
|
|
606
|
+
},
|
|
579
607
|
"page.state": { desc: "Get page state (modals, loading, etc.)", args: [] },
|
|
580
608
|
}
|
|
581
609
|
},
|
|
@@ -1464,7 +1492,7 @@ const ALL_SOCKET_TOOLS = [
|
|
|
1464
1492
|
"click_type", "click_type_submit", "type", "key", "type_submit",
|
|
1465
1493
|
"scroll", "scroll_to", "hover", "left_click_drag", "drag", "wait",
|
|
1466
1494
|
"computer",
|
|
1467
|
-
"page.read", "page.text", "page.state",
|
|
1495
|
+
"page.read", "page.text", "page.html", "page.save", "page.state",
|
|
1468
1496
|
"locate.role", "locate.text", "locate.label",
|
|
1469
1497
|
"tab.list", "tab.new", "tab.switch", "tab.close", "tab.move", "tab.name", "tab.unname", "tab.named",
|
|
1470
1498
|
"tab.group", "tab.ungroup", "tab.groups", "tab.reload",
|
|
@@ -2613,6 +2641,7 @@ const PRIMARY_ARG_MAP = {
|
|
|
2613
2641
|
grok: "query",
|
|
2614
2642
|
aistudio: "query",
|
|
2615
2643
|
"aistudio.build": "query",
|
|
2644
|
+
kimi: "query",
|
|
2616
2645
|
navigate: "url",
|
|
2617
2646
|
go: "url",
|
|
2618
2647
|
js: "code",
|
|
@@ -2818,11 +2847,16 @@ if (tool === "network.export" && outputPath !== undefined) {
|
|
|
2818
2847
|
toolArgs.output = outputPath;
|
|
2819
2848
|
}
|
|
2820
2849
|
|
|
2821
|
-
if ((tool === "screenshot" || tool === "record" || tool === "perf-audit") && outputPath && typeof outputPath !== "string") {
|
|
2850
|
+
if ((tool === "screenshot" || tool === "record" || tool === "perf-audit" || tool === "page.save") && outputPath && typeof outputPath !== "string") {
|
|
2822
2851
|
console.error("Error: --output requires a file path");
|
|
2823
2852
|
process.exit(1);
|
|
2824
2853
|
}
|
|
2825
2854
|
|
|
2855
|
+
if (tool === "page.save" && !outputPath) {
|
|
2856
|
+
console.error("Error: page.save requires --output <path>");
|
|
2857
|
+
process.exit(1);
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2826
2860
|
if (tool === "screenshot" && outputPath) {
|
|
2827
2861
|
toolArgs.savePath = outputPath;
|
|
2828
2862
|
if (options.full) toolArgs.full = true;
|
|
@@ -3294,6 +3328,21 @@ async function handleResponse(response) {
|
|
|
3294
3328
|
data = { response: data };
|
|
3295
3329
|
}
|
|
3296
3330
|
|
|
3331
|
+
if (tool === 'kimi' && typeof data === 'string') {
|
|
3332
|
+
data = { response: data };
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
if (tool === "page.save" && typeof data?.html === "string") {
|
|
3336
|
+
const saveTo = path.resolve(outputPath);
|
|
3337
|
+
fs.mkdirSync(path.dirname(saveTo), { recursive: true });
|
|
3338
|
+
fs.writeFileSync(saveTo, data.html);
|
|
3339
|
+
if (!wantJson) {
|
|
3340
|
+
console.log(`Saved rendered page HTML to ${saveTo}`);
|
|
3341
|
+
socket.end();
|
|
3342
|
+
process.exit(0);
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3297
3346
|
if (tool === "perf-audit" && outputPath) {
|
|
3298
3347
|
const saveTo = path.resolve(outputPath);
|
|
3299
3348
|
fs.mkdirSync(path.dirname(saveTo), { recursive: true });
|
|
@@ -3375,6 +3424,8 @@ async function handleResponse(response) {
|
|
|
3375
3424
|
console.log(data.pageContent);
|
|
3376
3425
|
} else if (tool === "page.text" && data?.text) {
|
|
3377
3426
|
console.log(data.text);
|
|
3427
|
+
} else if (tool === "page.html" && typeof data?.html === "string") {
|
|
3428
|
+
console.log(data.html);
|
|
3378
3429
|
} else if (tool === "emulate.device" && data?.devices) {
|
|
3379
3430
|
console.log("Available devices:\n");
|
|
3380
3431
|
const devices = data.devices;
|
|
@@ -3500,7 +3551,18 @@ async function handleResponse(response) {
|
|
|
3500
3551
|
if (meta.length > 0) {
|
|
3501
3552
|
console.error(`[${meta.join(" | ")}]`);
|
|
3502
3553
|
}
|
|
3503
|
-
|
|
3554
|
+
} else if (tool === "kimi" && data?.response) {
|
|
3555
|
+
console.log(data.response);
|
|
3556
|
+
const meta = [];
|
|
3557
|
+
if (data.model) meta.push(data.model);
|
|
3558
|
+
if (data.partial) meta.push("partial");
|
|
3559
|
+
if (Number.isFinite(data.tookMs)) meta.push(`${(data.tookMs / 1000).toFixed(1)}s`);
|
|
3560
|
+
if (meta.length > 0) console.error(`\n[${meta.join(' | ')}]`);
|
|
3561
|
+
if (data.url) console.error(`URL: ${data.url}`);
|
|
3562
|
+
if (data.warnings?.length) {
|
|
3563
|
+
for (const w of data.warnings) console.warn(`Warning: ${w}`);
|
|
3564
|
+
}
|
|
3565
|
+
} else if (tool === "perplexity" && data?.response) {
|
|
3504
3566
|
console.log(data.response);
|
|
3505
3567
|
const meta = [];
|
|
3506
3568
|
if (data.sources) meta.push(`${data.sources} sources`);
|
package/native/host-helpers.cjs
CHANGED
|
@@ -77,8 +77,23 @@ function formatToolContent(result, log = () => {}, options = {}) {
|
|
|
77
77
|
return text(output);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
// Handle Kimi validation results (must precede the Grok branch - same field names)
|
|
81
|
+
if (result.kimiValidate) {
|
|
82
|
+
let output = "## Kimi Validation Results\n\n";
|
|
83
|
+
output += `**Authenticated:** ${result.authenticated ? 'Yes' : 'No'}\n`;
|
|
84
|
+
output += `**Input Field:** ${result.inputFound ? 'Found' : 'Not Found'}\n`;
|
|
85
|
+
output += `**Send Button:** ${result.sendButtonFound ? 'Found' : 'Not Found'}\n\n`;
|
|
86
|
+
output += `**Available Models:** ${result.models.length > 0 ? result.models.join(', ') : 'None found'}\n`;
|
|
87
|
+
output += `**Expected Models:** ${result.expectedModels.join(', ')}\n\n`;
|
|
88
|
+
if (result.errors && result.errors.length > 0) {
|
|
89
|
+
output += `**Errors:**\n${result.errors.map(e => `- ${e}`).join('\n')}\n\n`;
|
|
90
|
+
}
|
|
91
|
+
output += `*Completed in ${result.tookMs}ms*`;
|
|
92
|
+
return text(output);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Handle Grok validation results
|
|
96
|
+
if (result.authenticated !== undefined && result.models !== undefined && result.expectedModels !== undefined) {
|
|
82
97
|
let output = "## Grok Validation Results\n\n";
|
|
83
98
|
output += `**Authenticated:** ${result.authenticated ? 'Yes' : 'No'}\n`;
|
|
84
99
|
output += `**Premium:** ${result.premium ? 'Yes' : 'No'}\n`;
|
|
@@ -936,6 +951,18 @@ function mapToolToMessage(tool, args, tabId) {
|
|
|
936
951
|
}
|
|
937
952
|
case "page.text":
|
|
938
953
|
return { type: "GET_PAGE_TEXT", ...baseMsg };
|
|
954
|
+
case "page.html":
|
|
955
|
+
case "page.save": {
|
|
956
|
+
if (a.selector !== undefined && (typeof a.selector !== "string" || a.selector.length === 0)) {
|
|
957
|
+
throw new Error("selector must be a non-empty string");
|
|
958
|
+
}
|
|
959
|
+
return {
|
|
960
|
+
type: "GET_PAGE_HTML",
|
|
961
|
+
selector: a.selector,
|
|
962
|
+
stripScripts: a["strip-scripts"] === true,
|
|
963
|
+
...baseMsg,
|
|
964
|
+
};
|
|
965
|
+
}
|
|
939
966
|
case "page.state":
|
|
940
967
|
return { type: "PAGE_STATE", ...baseMsg };
|
|
941
968
|
case "locate.role":
|
|
@@ -1188,6 +1215,22 @@ function mapToolToMessage(tool, args, tabId) {
|
|
|
1188
1215
|
...baseMsg,
|
|
1189
1216
|
};
|
|
1190
1217
|
}
|
|
1218
|
+
case "kimi":
|
|
1219
|
+
if (a.validate) {
|
|
1220
|
+
return {
|
|
1221
|
+
type: "KIMI_VALIDATE",
|
|
1222
|
+
...baseMsg
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
if (!a.query) throw new Error("query required");
|
|
1226
|
+
return {
|
|
1227
|
+
type: "KIMI_QUERY",
|
|
1228
|
+
query: a.query,
|
|
1229
|
+
model: a.model,
|
|
1230
|
+
withPage: a["with-page"],
|
|
1231
|
+
timeout: a.timeout ? parseInt(a.timeout, 10) * 1000 : 300000,
|
|
1232
|
+
...baseMsg
|
|
1233
|
+
};
|
|
1191
1234
|
case "window.new":
|
|
1192
1235
|
return {
|
|
1193
1236
|
type: "WINDOW_NEW",
|
package/native/host-sessions.cjs
CHANGED
package/native/host.cjs
CHANGED
|
@@ -12,6 +12,7 @@ const chatgptClient = require("./chatgpt-client.cjs");
|
|
|
12
12
|
const geminiClient = require("./gemini-client.cjs");
|
|
13
13
|
const perplexityClient = require("./perplexity-client.cjs");
|
|
14
14
|
const grokClient = require("./grok-client.cjs");
|
|
15
|
+
const kimiClient = require("./kimi-client.cjs");
|
|
15
16
|
const aistudioClient = require("./aistudio-client.cjs");
|
|
16
17
|
const aistudioBuild = require("./aistudio-build.cjs");
|
|
17
18
|
const { mapToolToMessage, mapComputerAction, formatToolContent, formatToolError, buildProviderUploadMessage } = require("./host-helpers.cjs");
|
|
@@ -523,6 +524,7 @@ async function runHostPlaybook(msg, request) {
|
|
|
523
524
|
onEvent: report,
|
|
524
525
|
beforeDispatch: async () => updateReceipt(receipt, "dispatched"),
|
|
525
526
|
afterDispatch: async ({ status, error }) => updateReceipt(receipt, status, { error }),
|
|
527
|
+
allowScript: params.allowScript === true,
|
|
526
528
|
});
|
|
527
529
|
}
|
|
528
530
|
|
|
@@ -1236,13 +1238,115 @@ function handleToolRequest(msg, socket, requestContext = requestStorage.getStore
|
|
|
1236
1238
|
}
|
|
1237
1239
|
sendToolResponse(socket, originalId, result, null);
|
|
1238
1240
|
}).catch((err) => {
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1241
|
+
sendToolResponse(socket, originalId, null, err.message);
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
if (extensionMsg.type === "KIMI_QUERY") {
|
|
1248
|
+
const { query, model, withPage, timeout } = extensionMsg;
|
|
1249
|
+
|
|
1250
|
+
queueAiRequest(async () => {
|
|
1251
|
+
// 1. Get page context if requested
|
|
1252
|
+
let pageContext = null;
|
|
1253
|
+
if (withPage) {
|
|
1254
|
+
const pageResult = await requestCallExtension(
|
|
1255
|
+
requestContext,
|
|
1256
|
+
"get_page_text",
|
|
1257
|
+
{ type: "GET_PAGE_TEXT", tabId: extensionMsg.tabId },
|
|
1258
|
+
45000,
|
|
1259
|
+
);
|
|
1260
|
+
if (pageResult && !pageResult.error) {
|
|
1261
|
+
pageContext = {
|
|
1262
|
+
url: pageResult.url,
|
|
1263
|
+
text: pageResult.text || pageResult.pageContent || ""
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// 2. Build full prompt
|
|
1269
|
+
let fullPrompt = query || "";
|
|
1270
|
+
if (pageContext) {
|
|
1271
|
+
fullPrompt = `Page: ${pageContext.url}\n\n${pageContext.text}\n\n---\n\n${fullPrompt}`;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// 3. Call Kimi client (uses generic browser primitives, no provider CDP types)
|
|
1275
|
+
const result = await kimiClient.query({
|
|
1276
|
+
prompt: fullPrompt,
|
|
1277
|
+
extractionPrompt: query,
|
|
1278
|
+
signal: requestContext.signal,
|
|
1279
|
+
model: model,
|
|
1280
|
+
timeout: timeout || 300000,
|
|
1281
|
+
createTab: () => requestCallExtension(
|
|
1282
|
+
requestContext,
|
|
1283
|
+
"create_tab",
|
|
1284
|
+
{ type: "NEW_TAB", url: "https://www.kimi.com/" },
|
|
1285
|
+
),
|
|
1286
|
+
closeTab: (tabIdToClose) => requestCallExtension(requestContext, "close_tab", { type: "CLOSE_TAB", tabId: tabIdToClose }, 45000, true),
|
|
1287
|
+
jsEval: (tabId, code) => requestCallExtension(
|
|
1288
|
+
requestContext,
|
|
1289
|
+
"js_eval",
|
|
1290
|
+
{ type: "EXECUTE_JAVASCRIPT", tabId, code },
|
|
1291
|
+
),
|
|
1292
|
+
log: (msg) => log(`[kimi] ${msg}`)
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1295
|
+
return result;
|
|
1296
|
+
}).then((result) => {
|
|
1297
|
+
const response = {
|
|
1298
|
+
response: result.response,
|
|
1299
|
+
model: result.model,
|
|
1300
|
+
tookMs: result.tookMs
|
|
1301
|
+
};
|
|
1302
|
+
if (result.partial) {
|
|
1303
|
+
response.partial = true;
|
|
1304
|
+
}
|
|
1305
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
1306
|
+
response.warnings = result.warnings;
|
|
1307
|
+
}
|
|
1308
|
+
if (result.modelSelectionFailed) {
|
|
1309
|
+
response.modelSelectionFailed = true;
|
|
1310
|
+
}
|
|
1311
|
+
if (result.url) {
|
|
1312
|
+
response.url = result.url;
|
|
1313
|
+
}
|
|
1314
|
+
sendToolResponse(socket, originalId, response, null);
|
|
1315
|
+
}).catch((err) => {
|
|
1316
|
+
sendToolResponse(socket, originalId, null, err.message);
|
|
1317
|
+
});
|
|
1318
|
+
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
if (extensionMsg.type === "KIMI_VALIDATE") {
|
|
1323
|
+
queueAiRequest(async () => {
|
|
1324
|
+
const result = await kimiClient.validate({
|
|
1325
|
+
signal: requestContext.signal,
|
|
1326
|
+
createTab: () => requestCallExtension(
|
|
1327
|
+
requestContext,
|
|
1328
|
+
"create_tab",
|
|
1329
|
+
{ type: "NEW_TAB", url: "https://www.kimi.com/" },
|
|
1330
|
+
),
|
|
1331
|
+
closeTab: (tabIdToClose) => requestCallExtension(requestContext, "close_tab", { type: "CLOSE_TAB", tabId: tabIdToClose }, 45000, true),
|
|
1332
|
+
jsEval: (tabId, code) => requestCallExtension(
|
|
1333
|
+
requestContext,
|
|
1334
|
+
"js_eval",
|
|
1335
|
+
{ type: "EXECUTE_JAVASCRIPT", tabId, code },
|
|
1336
|
+
),
|
|
1337
|
+
log: (msg) => log(`[kimi] ${msg}`)
|
|
1338
|
+
});
|
|
1339
|
+
return result;
|
|
1340
|
+
}).then((result) => {
|
|
1341
|
+
sendToolResponse(socket, originalId, result, null);
|
|
1342
|
+
}).catch((err) => {
|
|
1343
|
+
sendToolResponse(socket, originalId, null, err.message);
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1244
1348
|
|
|
1245
|
-
|
|
1349
|
+
if (extensionMsg.type === "AISTUDIO_QUERY") {
|
|
1246
1350
|
const { query, model, withPage, timeout } = extensionMsg;
|
|
1247
1351
|
|
|
1248
1352
|
queueAiRequest(async () => {
|