@todoforai/edge 0.13.17 → 0.13.19
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.js +168 -54
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47977,10 +47977,10 @@ function setConnectionContext(get) {
|
|
|
47977
47977
|
function getConnectionEnv() {
|
|
47978
47978
|
if (!getter)
|
|
47979
47979
|
return {};
|
|
47980
|
-
const { apiUrl,
|
|
47981
|
-
if (!apiUrl || !
|
|
47980
|
+
const { apiUrl, sessionToken } = getter();
|
|
47981
|
+
if (!apiUrl || !sessionToken)
|
|
47982
47982
|
return {};
|
|
47983
|
-
return { TODOFORAI_API_URL: apiUrl, TODOFORAI_API_TOKEN:
|
|
47983
|
+
return { TODOFORAI_API_URL: apiUrl, TODOFORAI_API_TOKEN: sessionToken };
|
|
47984
47984
|
}
|
|
47985
47985
|
|
|
47986
47986
|
// src/constants.ts
|
|
@@ -48033,7 +48033,8 @@ var EF = {
|
|
|
48033
48033
|
FRONTEND_FILE_CHUNK_RESULT: "frontend:file_chunk_result"
|
|
48034
48034
|
};
|
|
48035
48035
|
var S2E = {
|
|
48036
|
-
EDGE_CONFIG_UPDATE: "edge:config_update"
|
|
48036
|
+
EDGE_CONFIG_UPDATE: "edge:config_update",
|
|
48037
|
+
SESSION_TOKEN: "edge:session_token"
|
|
48037
48038
|
};
|
|
48038
48039
|
var msg = {
|
|
48039
48040
|
edgeStatus(edgeId, status) {
|
|
@@ -48824,6 +48825,48 @@ var tool_catalog_default = {
|
|
|
48824
48825
|
description: "Use to send WhatsApp messages/files/media/locations/polls from CLI. QR-code login via `mudslide login`.",
|
|
48825
48826
|
versionCmd: "mudslide --version 2>/dev/null | head -1"
|
|
48826
48827
|
},
|
|
48828
|
+
slack: {
|
|
48829
|
+
category: "development",
|
|
48830
|
+
pkg: "slack-cli",
|
|
48831
|
+
installer: "binary",
|
|
48832
|
+
label: "Slack",
|
|
48833
|
+
statusCmd: "slack-cli auth list 2>&1 | grep -q 'Team' && echo authenticated",
|
|
48834
|
+
loginCmd: "slack-cli login",
|
|
48835
|
+
credentialPaths: [
|
|
48836
|
+
"~/.slack/credentials.json"
|
|
48837
|
+
],
|
|
48838
|
+
capabilities: "Build & deploy Slack apps, manage workspaces & triggers, run datastore queries, tail logs — official Slack CLI.",
|
|
48839
|
+
description: "Use for Slack platform development: scaffold/run/deploy Slack apps, manage triggers and datastores, manage workspace auth. `slack-cli login` to authenticate. Invoked as `slack-cli` to avoid colliding with the Slack desktop app's `slack` binary.",
|
|
48840
|
+
versionCmd: "slack-cli version 2>/dev/null | head -1",
|
|
48841
|
+
binName: "slack-cli",
|
|
48842
|
+
binary: {
|
|
48843
|
+
"linux-x86_64": {
|
|
48844
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_linux_amd64.tar.gz",
|
|
48845
|
+
archive: "tar.gz",
|
|
48846
|
+
extract: "bin/slack"
|
|
48847
|
+
},
|
|
48848
|
+
"linux-aarch64": {
|
|
48849
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_linux_arm64.tar.gz",
|
|
48850
|
+
archive: "tar.gz",
|
|
48851
|
+
extract: "bin/slack"
|
|
48852
|
+
},
|
|
48853
|
+
"darwin-x86_64": {
|
|
48854
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_macOS_amd64.tar.gz",
|
|
48855
|
+
archive: "tar.gz",
|
|
48856
|
+
extract: "bin/slack"
|
|
48857
|
+
},
|
|
48858
|
+
"darwin-aarch64": {
|
|
48859
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_macOS_arm64.tar.gz",
|
|
48860
|
+
archive: "tar.gz",
|
|
48861
|
+
extract: "bin/slack"
|
|
48862
|
+
},
|
|
48863
|
+
"windows-x86_64": {
|
|
48864
|
+
url: "https://github.com/slackapi/slack-cli/releases/download/v4.2.0/slack_cli_4.2.0_windows_64-bit.zip",
|
|
48865
|
+
archive: "zip",
|
|
48866
|
+
extract: "bin/slack.exe"
|
|
48867
|
+
}
|
|
48868
|
+
}
|
|
48869
|
+
},
|
|
48827
48870
|
"telegram-send": {
|
|
48828
48871
|
category: "messaging",
|
|
48829
48872
|
pkg: "telegram-send",
|
|
@@ -49208,7 +49251,7 @@ var tool_catalog_default = {
|
|
|
49208
49251
|
preinstallCloud: true,
|
|
49209
49252
|
label: "Browser",
|
|
49210
49253
|
capabilities: "Headless browser automation, web scraping, accessibility tree snapshots, screenshots, PDF generation",
|
|
49211
|
-
description: "Headless browser. Use for JS-rendered pages, scraping, screenshots, PDFs, and automated flows. Default browser — prefer over `todoforai-browser` unless the user's own session is needed.",
|
|
49254
|
+
description: "Headless browser. Use for JS-rendered pages, scraping, screenshots, PDFs, and automated flows. Default browser — prefer over `todoforai-browser` unless the user's own session is needed. On a PC with a display, prefer a visible window the user can watch and interact with (needed for CAPTCHA/MFA/login): launch a separate Chrome with `google-chrome --remote-debugging-port=9222 --user-data-dir=$HOME/.config/google-chrome-cdp >/tmp/chrome-cdp.log 2>&1 &` (own data-dir, leaves the user's running Chrome untouched), then attach with `agent-browser --cdp 9222 <command>`. Use headless only on the cloud or when no display is available.",
|
|
49212
49255
|
versionCmd: "agent-browser --version 2>/dev/null | head -1"
|
|
49213
49256
|
},
|
|
49214
49257
|
"todoforai-browser": {
|
|
@@ -49252,7 +49295,6 @@ var tool_catalog_default = {
|
|
|
49252
49295
|
description: "Explore a codebase with a read-only sub-agent. Streams findings live.",
|
|
49253
49296
|
versionCmd: "tfa-explore --version 2>/dev/null | head -1",
|
|
49254
49297
|
installCmd: "bun add -g @todoforai/tfa-explore",
|
|
49255
|
-
preinstall: true,
|
|
49256
49298
|
preinstallCloud: true,
|
|
49257
49299
|
internal: true
|
|
49258
49300
|
},
|
|
@@ -49265,7 +49307,6 @@ var tool_catalog_default = {
|
|
|
49265
49307
|
description: "Review a git diff with a read-only sub-agent.",
|
|
49266
49308
|
versionCmd: "tfa-review --version 2>/dev/null | head -1",
|
|
49267
49309
|
installCmd: "bun add -g @todoforai/tfa-review",
|
|
49268
|
-
preinstall: true,
|
|
49269
49310
|
preinstallCloud: true,
|
|
49270
49311
|
internal: true
|
|
49271
49312
|
},
|
|
@@ -49290,7 +49331,6 @@ var tool_catalog_default = {
|
|
|
49290
49331
|
versionCmd: "tfa-vault --version 2>/dev/null | head -1",
|
|
49291
49332
|
statusCmd: "tfa-vault whoami",
|
|
49292
49333
|
installCmd: "bun add -g @todoforai/vault",
|
|
49293
|
-
preinstall: true,
|
|
49294
49334
|
preinstallCloud: true
|
|
49295
49335
|
},
|
|
49296
49336
|
ripgrep: {
|
|
@@ -49582,6 +49622,17 @@ function isToolInstalled(name) {
|
|
|
49582
49622
|
}
|
|
49583
49623
|
return whichWithTools(name) !== null;
|
|
49584
49624
|
}
|
|
49625
|
+
function findReferencedTools(content) {
|
|
49626
|
+
const stripped = content.replace(/"(?:[^"\\]|\\.)*"/g, '""').replace(/'(?:[^'\\]|\\.)*'/g, "''");
|
|
49627
|
+
return Object.keys(TOOL_CATALOG).filter((name) => {
|
|
49628
|
+
const esc = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
49629
|
+
const re = new RegExp(String.raw`(?:^|[|;&\n]|&&|\|\||` + String.raw`\$\(|` + "`" + String.raw`|xargs\s+|sudo\s+|env\s+)\s*` + esc + String.raw`\b(?!-)`, "m");
|
|
49630
|
+
return re.test(stripped);
|
|
49631
|
+
});
|
|
49632
|
+
}
|
|
49633
|
+
function findMissingTools(content) {
|
|
49634
|
+
return findReferencedTools(content).filter((name) => TOOL_CATALOG[name].installer !== "system" && !isToolInstalled(name));
|
|
49635
|
+
}
|
|
49585
49636
|
async function installBinary(name) {
|
|
49586
49637
|
const urlFunc = BINARY_URL_FUNCS[name];
|
|
49587
49638
|
if (!urlFunc) {
|
|
@@ -49655,6 +49706,15 @@ function findFileRecursive(dir, names) {
|
|
|
49655
49706
|
}
|
|
49656
49707
|
return null;
|
|
49657
49708
|
}
|
|
49709
|
+
function getInstallCommand(name) {
|
|
49710
|
+
const e = TOOL_CATALOG[name];
|
|
49711
|
+
return e.installCmd || {
|
|
49712
|
+
npm: `npm install --prefix ~/.todoforai/tools ${e.pkg}`,
|
|
49713
|
+
bun: `bun add --cwd ~/.todoforai/tools ${e.pkg}`,
|
|
49714
|
+
pip: `pip install ${e.pkg}`,
|
|
49715
|
+
binary: `download ${e.pkg}`
|
|
49716
|
+
}[e.installer] || `install ${e.pkg}`;
|
|
49717
|
+
}
|
|
49658
49718
|
function installWithNpm(name, pkg) {
|
|
49659
49719
|
const TIMEOUT_MS = 120000;
|
|
49660
49720
|
log2("info", `Installing ${name} via npm (${pkg})`);
|
|
@@ -49756,11 +49816,11 @@ function installWithPip(name, pkg) {
|
|
|
49756
49816
|
log2("info", `Installing ${name} via pip (${pkg})`);
|
|
49757
49817
|
const args = useVenv ? ["-m", "pip", "install", pkg] : ["-m", "pip", "install", "--user", pkg];
|
|
49758
49818
|
const result = spawnSync(python, args, { stdio: "pipe", timeout: 120000 });
|
|
49759
|
-
|
|
49760
|
-
|
|
49761
|
-
|
|
49762
|
-
|
|
49763
|
-
|
|
49819
|
+
const stderr = result.stderr?.toString().trim() || "";
|
|
49820
|
+
if (result.signal)
|
|
49821
|
+
throw new Error(`pip install killed by ${result.signal}${result.signal === "SIGTERM" ? " (likely timed out after 120s)" : ""}`);
|
|
49822
|
+
if (result.status !== 0)
|
|
49823
|
+
throw new Error(`pip install failed (exit ${result.status}): ${stderr || result.stdout?.toString().trim() || "(empty)"}`);
|
|
49764
49824
|
}
|
|
49765
49825
|
var INSTALLERS = {
|
|
49766
49826
|
npm: installWithNpm,
|
|
@@ -49829,6 +49889,17 @@ function uninstallTool(name) {
|
|
|
49829
49889
|
return false;
|
|
49830
49890
|
}
|
|
49831
49891
|
}
|
|
49892
|
+
async function autoInstallMissingTools(content) {
|
|
49893
|
+
const lines = [];
|
|
49894
|
+
for (const name of findMissingTools(content)) {
|
|
49895
|
+
const ok = await ensureTool(name) && isToolInstalled(name);
|
|
49896
|
+
lines.push(`$ ${getInstallCommand(name)}
|
|
49897
|
+
[${ok ? "installed" : "install failed"}: ${name}]`);
|
|
49898
|
+
}
|
|
49899
|
+
return lines.length ? lines.join(`
|
|
49900
|
+
`) + `
|
|
49901
|
+
` : "";
|
|
49902
|
+
}
|
|
49832
49903
|
function execShellAsync(cmd, env, timeout) {
|
|
49833
49904
|
return new Promise((resolve) => {
|
|
49834
49905
|
execFile("sh", ["-c", cmd], { env, timeout, encoding: "utf-8", maxBuffer: 1024 * 1024 }, (err, stdout, stderr) => {
|
|
@@ -51531,6 +51602,48 @@ async function readFdTarget(pid, fd3) {
|
|
|
51531
51602
|
}
|
|
51532
51603
|
var pauseDetector = new PtyPauseDetector;
|
|
51533
51604
|
|
|
51605
|
+
// ../../packages/shared-fbe/src/outputLimits.ts
|
|
51606
|
+
var MAX_RESULT_LINES = 100;
|
|
51607
|
+
var MAX_LINE_LEN = 300;
|
|
51608
|
+
var MAX_TOTAL_LEN = 1e5;
|
|
51609
|
+
var STREAM_FIRST = 1e4;
|
|
51610
|
+
var STREAM_LAST = 1e4;
|
|
51611
|
+
var RUN_OUTPUT_CAP = 256 * 1024;
|
|
51612
|
+
var OUTPUT_POLICIES = {
|
|
51613
|
+
safe: { firstLimit: STREAM_FIRST, lastLimit: STREAM_LAST, hardCap: STREAM_FIRST + STREAM_LAST },
|
|
51614
|
+
full: { firstLimit: Infinity, lastLimit: 0, hardCap: RUN_OUTPUT_CAP },
|
|
51615
|
+
raw: { firstLimit: Infinity, lastLimit: 0, hardCap: Infinity }
|
|
51616
|
+
};
|
|
51617
|
+
var DEFAULT_OUTPUT_MODE = "safe";
|
|
51618
|
+
function resolveOutputPolicy(mode) {
|
|
51619
|
+
return OUTPUT_POLICIES[mode] ?? OUTPUT_POLICIES[DEFAULT_OUTPUT_MODE];
|
|
51620
|
+
}
|
|
51621
|
+
function truncateLines(text, { maxLines = MAX_RESULT_LINES, maxLineLen = MAX_LINE_LEN, maxTotalLen = MAX_TOTAL_LEN } = {}, unit = "matches") {
|
|
51622
|
+
let lines = text.split(`
|
|
51623
|
+
`).filter((l) => l.trim());
|
|
51624
|
+
const overflow = lines.length - maxLines;
|
|
51625
|
+
if (overflow > 0)
|
|
51626
|
+
lines = lines.slice(0, maxLines);
|
|
51627
|
+
lines = lines.map((line) => line.length > maxLineLen ? line.slice(0, maxLineLen) + ` ...[+${line.length - maxLineLen} chars]` : line);
|
|
51628
|
+
let output = lines.join(`
|
|
51629
|
+
`);
|
|
51630
|
+
if (overflow > 0)
|
|
51631
|
+
output += `
|
|
51632
|
+
... (${overflow} more ${unit} truncated)`;
|
|
51633
|
+
if (output.length > maxTotalLen)
|
|
51634
|
+
output = output.slice(0, maxTotalLen) + `
|
|
51635
|
+
... (output truncated)`;
|
|
51636
|
+
return output;
|
|
51637
|
+
}
|
|
51638
|
+
function formatTruncationNotice(totalLen, firstLimit, lastPart) {
|
|
51639
|
+
const dropped = totalLen - firstLimit - lastPart.length;
|
|
51640
|
+
return `
|
|
51641
|
+
|
|
51642
|
+
... [truncated ${dropped} chars] ...
|
|
51643
|
+
|
|
51644
|
+
${lastPart}`;
|
|
51645
|
+
}
|
|
51646
|
+
|
|
51534
51647
|
// src/shell.ts
|
|
51535
51648
|
var IS_WIN = os6.platform() === "win32";
|
|
51536
51649
|
var HAS_BUN = typeof globalThis.Bun !== "undefined";
|
|
@@ -51550,6 +51663,14 @@ function whichSync(name) {
|
|
|
51550
51663
|
}
|
|
51551
51664
|
return null;
|
|
51552
51665
|
}
|
|
51666
|
+
function isAccessibleDir(p10) {
|
|
51667
|
+
try {
|
|
51668
|
+
fs8.accessSync(p10, fs8.constants.X_OK);
|
|
51669
|
+
return fs8.statSync(p10).isDirectory();
|
|
51670
|
+
} catch {
|
|
51671
|
+
return false;
|
|
51672
|
+
}
|
|
51673
|
+
}
|
|
51553
51674
|
function getShellCommand(content) {
|
|
51554
51675
|
if (!IS_WIN)
|
|
51555
51676
|
return { shell: "/bin/bash", args: ["-c", content] };
|
|
@@ -51567,26 +51688,24 @@ function getShellCommand(content) {
|
|
|
51567
51688
|
}
|
|
51568
51689
|
return { shell: "cmd.exe", args: ["/c", "chcp 65001>nul && " + content] };
|
|
51569
51690
|
}
|
|
51570
|
-
var STREAM_FIRST = 1e4;
|
|
51571
|
-
var STREAM_LAST = 1e4;
|
|
51572
51691
|
|
|
51573
51692
|
class OutputBuffer {
|
|
51574
|
-
firstLimit;
|
|
51575
|
-
lastLimit;
|
|
51576
51693
|
firstPart = "";
|
|
51577
51694
|
lastPart = "";
|
|
51578
51695
|
totalLen = 0;
|
|
51579
51696
|
truncated = false;
|
|
51580
51697
|
truncMsgSent = false;
|
|
51581
|
-
|
|
51582
|
-
|
|
51583
|
-
|
|
51698
|
+
headLimit;
|
|
51699
|
+
lastLimit;
|
|
51700
|
+
constructor(policy = OUTPUT_POLICIES[DEFAULT_OUTPUT_MODE]) {
|
|
51701
|
+
this.headLimit = Math.min(policy.firstLimit, policy.hardCap);
|
|
51702
|
+
this.lastLimit = Math.min(policy.lastLimit, policy.hardCap - this.headLimit);
|
|
51584
51703
|
}
|
|
51585
51704
|
append(text) {
|
|
51586
51705
|
this.totalLen += text.length;
|
|
51587
51706
|
let toStream = "";
|
|
51588
|
-
if (this.firstPart.length < this.
|
|
51589
|
-
const remaining = this.
|
|
51707
|
+
if (this.firstPart.length < this.headLimit) {
|
|
51708
|
+
const remaining = this.headLimit - this.firstPart.length;
|
|
51590
51709
|
toStream = text.slice(0, remaining);
|
|
51591
51710
|
this.firstPart += toStream;
|
|
51592
51711
|
text = text.slice(remaining);
|
|
@@ -51594,19 +51713,14 @@ class OutputBuffer {
|
|
|
51594
51713
|
if (text) {
|
|
51595
51714
|
if (!this.truncated)
|
|
51596
51715
|
this.truncated = true;
|
|
51597
|
-
this.lastPart = (this.lastPart + text).slice(-this.lastLimit);
|
|
51716
|
+
this.lastPart = this.lastLimit > 0 ? (this.lastPart + text).slice(-this.lastLimit) : "";
|
|
51598
51717
|
}
|
|
51599
51718
|
return toStream;
|
|
51600
51719
|
}
|
|
51601
51720
|
getTruncationNotice() {
|
|
51602
51721
|
if (this.truncated && !this.truncMsgSent) {
|
|
51603
51722
|
this.truncMsgSent = true;
|
|
51604
|
-
|
|
51605
|
-
return `
|
|
51606
|
-
|
|
51607
|
-
... [truncated ${dropped} chars] ...
|
|
51608
|
-
|
|
51609
|
-
${this.lastPart}`;
|
|
51723
|
+
return formatTruncationNotice(this.totalLen, this.firstPart.length, this.lastPart);
|
|
51610
51724
|
}
|
|
51611
51725
|
return "";
|
|
51612
51726
|
}
|
|
@@ -51634,12 +51748,12 @@ var processes = new Map;
|
|
|
51634
51748
|
var outputBuffers = new Map;
|
|
51635
51749
|
var completionResolvers = new Map;
|
|
51636
51750
|
var exitedOutputByPid = new Map;
|
|
51637
|
-
async function executeBlock(blockId, content, send, todoId, messageId, timeout, cwd, manual = false, runMode, edgeId, agentSettingsId = "", keepAliveOnTimeout = false) {
|
|
51751
|
+
async function executeBlock(blockId, content, send, todoId, messageId, timeout, cwd, manual = false, runMode, edgeId, agentSettingsId = "", keepAliveOnTimeout = false, outputMode = DEFAULT_OUTPUT_MODE) {
|
|
51638
51752
|
if (processes.has(blockId)) {
|
|
51639
51753
|
console.log(`[shell] killing existing process for blockId=${blockId}`);
|
|
51640
51754
|
interruptBlock(blockId);
|
|
51641
51755
|
}
|
|
51642
|
-
const buf = new OutputBuffer;
|
|
51756
|
+
const buf = new OutputBuffer(resolveOutputPolicy(outputMode));
|
|
51643
51757
|
outputBuffers.set(blockId, buf);
|
|
51644
51758
|
try {
|
|
51645
51759
|
const tmpDir = path5.join(os6.tmpdir(), "todoforai");
|
|
@@ -51647,10 +51761,16 @@ async function executeBlock(blockId, content, send, todoId, messageId, timeout,
|
|
|
51647
51761
|
fs8.mkdirSync(tmpDir, { recursive: true });
|
|
51648
51762
|
if (cwd) {
|
|
51649
51763
|
const expanded = cwd.replace(/^~/, process.env.HOME || "~");
|
|
51650
|
-
cwd =
|
|
51764
|
+
cwd = isAccessibleDir(expanded) ? expanded : tmpDir;
|
|
51651
51765
|
} else {
|
|
51652
51766
|
cwd = tmpDir;
|
|
51653
51767
|
}
|
|
51768
|
+
const installNotice = await autoInstallMissingTools(content);
|
|
51769
|
+
if (installNotice) {
|
|
51770
|
+
const toStream = buf.append(installNotice);
|
|
51771
|
+
if (toStream)
|
|
51772
|
+
await send(msg.shellBlockResult(todoId, blockId, toStream, messageId));
|
|
51773
|
+
}
|
|
51654
51774
|
await send({
|
|
51655
51775
|
type: "BLOCK_UPDATE",
|
|
51656
51776
|
payload: { todoId, blockId, messageId, updates: { status: "RUNNING" } }
|
|
@@ -51815,7 +51935,7 @@ async function executeBlock(blockId, content, send, todoId, messageId, timeout,
|
|
|
51815
51935
|
spawnWithPipes();
|
|
51816
51936
|
}
|
|
51817
51937
|
} catch (e) {
|
|
51818
|
-
await send(msg.shellBlockResult(todoId, blockId, `Error creating process: ${e.message}`, messageId));
|
|
51938
|
+
await send(msg.shellBlockResult(todoId, blockId, `Error creating process: ${e.message} (cwd: ${cwd})`, messageId));
|
|
51819
51939
|
const resolver = completionResolvers.get(blockId);
|
|
51820
51940
|
if (resolver) {
|
|
51821
51941
|
resolver();
|
|
@@ -52392,7 +52512,7 @@ function detectContentType(output, cmd) {
|
|
|
52392
52512
|
return { result: output };
|
|
52393
52513
|
}
|
|
52394
52514
|
register("execute_shell_command", async (args, client) => {
|
|
52395
|
-
const { cmd, cwd = args.root_path ?? "", todoId = "", messageId = "", blockId = "", agentSettingsId = "", pid: resumePid = 0 } = args;
|
|
52515
|
+
const { cmd, cwd = args.root_path ?? "", todoId = "", messageId = "", blockId = "", agentSettingsId = "", pid: resumePid = 0, output: outputMode = DEFAULT_OUTPUT_MODE } = args;
|
|
52396
52516
|
const timeout = Math.max(args.timeout ?? 120, client?.maxTimeout ?? 0);
|
|
52397
52517
|
const canStream = !!(todoId && blockId && client);
|
|
52398
52518
|
if (!canStream) {
|
|
@@ -52433,7 +52553,7 @@ register("execute_shell_command", async (args, client) => {
|
|
|
52433
52553
|
}
|
|
52434
52554
|
try {
|
|
52435
52555
|
await send(msg.shellBlockStart(todoId, blockId, "execute", messageId));
|
|
52436
|
-
await executeBlock(blockId, execCmd, send, todoId, messageId, timeout, cwd, false, "internal", undefined, agentSettingsId, true);
|
|
52556
|
+
await executeBlock(blockId, execCmd, send, todoId, messageId, timeout, cwd, false, "internal", undefined, agentSettingsId, true, outputMode);
|
|
52437
52557
|
await waitForCompletion(blockId, (timeout + 5) * 1000);
|
|
52438
52558
|
const rawOutput = getBlockRawOutput(blockId);
|
|
52439
52559
|
let output = rawOutput ?? getBlockOutput(blockId);
|
|
@@ -52563,17 +52683,10 @@ register("search_files", async (args) => {
|
|
|
52563
52683
|
});
|
|
52564
52684
|
if (code === 0) {
|
|
52565
52685
|
let output = stdout;
|
|
52566
|
-
const lines = output.split(`
|
|
52567
|
-
`).filter((l) => l.trim());
|
|
52568
|
-
if (lines.length > head) {
|
|
52569
|
-
output = lines.slice(0, head).join(`
|
|
52570
|
-
`) + `
|
|
52571
|
-
... (${lines.length - head} more matches truncated)`;
|
|
52572
|
-
}
|
|
52573
52686
|
if ((cwd || searchPath) && output) {
|
|
52574
52687
|
const searchBase = searchPath && fs11.existsSync(searchPath) && fs11.statSync(searchPath).isDirectory() ? searchPath : path8.dirname(searchPath);
|
|
52575
52688
|
const bases = Array.from(new Set([cwd, searchBase].filter(Boolean)));
|
|
52576
|
-
const
|
|
52689
|
+
const lines = output.split(`
|
|
52577
52690
|
`).map((line) => {
|
|
52578
52691
|
if (line.includes(":")) {
|
|
52579
52692
|
const colonIdx = line.indexOf(":");
|
|
@@ -52583,21 +52696,14 @@ register("search_files", async (args) => {
|
|
|
52583
52696
|
const candidates = [filePart, ...bases.map((b) => path8.relative(b, filePart))].filter((p11) => (p11.match(/\.\.\//g) || []).length <= 2);
|
|
52584
52697
|
filePart = candidates.reduce((a, b) => a.length <= b.length ? a : b, filePart);
|
|
52585
52698
|
} catch {}
|
|
52586
|
-
|
|
52587
|
-
if (fullLine.length > 300) {
|
|
52588
|
-
fullLine = fullLine.slice(0, 300) + "...";
|
|
52589
|
-
}
|
|
52590
|
-
return fullLine;
|
|
52699
|
+
return filePart + rest;
|
|
52591
52700
|
}
|
|
52592
52701
|
return line;
|
|
52593
52702
|
});
|
|
52594
|
-
output =
|
|
52703
|
+
output = lines.join(`
|
|
52595
52704
|
`);
|
|
52596
52705
|
}
|
|
52597
|
-
|
|
52598
|
-
output = output.slice(0, 1e5) + `
|
|
52599
|
-
... (output truncated)`;
|
|
52600
|
-
return { result: output };
|
|
52706
|
+
return { result: truncateLines(output, { maxLines: head }) };
|
|
52601
52707
|
}
|
|
52602
52708
|
if (code === 1)
|
|
52603
52709
|
return { result: "No matches found." };
|
|
@@ -52889,6 +52995,7 @@ class TODOforAIEdge {
|
|
|
52889
52995
|
connected = false;
|
|
52890
52996
|
edgeId = "";
|
|
52891
52997
|
userId = "";
|
|
52998
|
+
sessionToken = "";
|
|
52892
52999
|
debug;
|
|
52893
53000
|
maxTimeout;
|
|
52894
53001
|
wsUrl;
|
|
@@ -52914,7 +53021,7 @@ class TODOforAIEdge {
|
|
|
52914
53021
|
this.wsUrl = getWsUrl(this.api.apiUrl);
|
|
52915
53022
|
this.addWorkspacePath = config.addWorkspacePath;
|
|
52916
53023
|
this.browserExtensionBridge = new BrowserExtensionBridge(this.debug);
|
|
52917
|
-
setConnectionContext(() => ({ apiUrl: this.api.apiUrl,
|
|
53024
|
+
setConnectionContext(() => ({ apiUrl: this.api.apiUrl, sessionToken: this.sessionToken }));
|
|
52918
53025
|
}
|
|
52919
53026
|
get apiUrl() {
|
|
52920
53027
|
return this.api.apiUrl;
|
|
@@ -53124,6 +53231,13 @@ class TODOforAIEdge {
|
|
|
53124
53231
|
case S2E.EDGE_CONFIG_UPDATE:
|
|
53125
53232
|
run(async () => this.handleEdgeConfigUpdate(payload));
|
|
53126
53233
|
break;
|
|
53234
|
+
case S2E.SESSION_TOKEN:
|
|
53235
|
+
if (typeof payload.token === "string" && payload.token.startsWith("dst_")) {
|
|
53236
|
+
this.sessionToken = payload.token;
|
|
53237
|
+
if (this.debug)
|
|
53238
|
+
console.log(`[recv] session token (expires in ${payload.expiresIn}s)`);
|
|
53239
|
+
}
|
|
53240
|
+
break;
|
|
53127
53241
|
case FE.EDGE_CD:
|
|
53128
53242
|
run(() => handleCd(payload, send, this.edgeConfig, (u) => this.updateConfig(u)));
|
|
53129
53243
|
break;
|