@vm0/cli 9.119.2 → 9.119.3
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/{chunk-PS4P6JB6.js → chunk-6UFVJSUZ.js} +352 -413
- package/{chunk-PS4P6JB6.js.map → chunk-6UFVJSUZ.js.map} +1 -1
- package/index.js +153 -292
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/zero.js +27 -430
- package/zero.js.map +1 -1
package/package.json
CHANGED
package/zero.js
CHANGED
|
@@ -18,15 +18,11 @@ import {
|
|
|
18
18
|
createPhoneCall,
|
|
19
19
|
createSkill,
|
|
20
20
|
createZeroAgent,
|
|
21
|
-
createZeroComputerConnector,
|
|
22
|
-
createZeroConnectorSession,
|
|
23
21
|
createZeroRun,
|
|
24
22
|
decodeCliTokenPayload,
|
|
25
23
|
decodeZeroTokenPayload,
|
|
26
24
|
deleteSkill,
|
|
27
25
|
deleteZeroAgent,
|
|
28
|
-
deleteZeroComputerConnector,
|
|
29
|
-
deleteZeroConnector,
|
|
30
26
|
deleteZeroOrg,
|
|
31
27
|
deleteZeroOrgModelProvider,
|
|
32
28
|
deleteZeroOrgSecret,
|
|
@@ -44,7 +40,6 @@ import {
|
|
|
44
40
|
getActiveOrg,
|
|
45
41
|
getApiUrl,
|
|
46
42
|
getAuthMethodsForType,
|
|
47
|
-
getBaseUrl,
|
|
48
43
|
getComputerUseHost,
|
|
49
44
|
getConnectorDerivedNames,
|
|
50
45
|
getConnectorEnvironmentMapping,
|
|
@@ -65,7 +60,6 @@ import {
|
|
|
65
60
|
getZeroAgentInstructions,
|
|
66
61
|
getZeroAgentUserConnectors,
|
|
67
62
|
getZeroConnector,
|
|
68
|
-
getZeroConnectorSession,
|
|
69
63
|
getZeroOrg,
|
|
70
64
|
getZeroOrgMembers,
|
|
71
65
|
getZeroRun,
|
|
@@ -131,7 +125,7 @@ import {
|
|
|
131
125
|
upsertZeroOrgModelProvider,
|
|
132
126
|
withErrorHandler,
|
|
133
127
|
zeroAgentCustomSkillNameSchema
|
|
134
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-6UFVJSUZ.js";
|
|
135
129
|
import {
|
|
136
130
|
__toESM,
|
|
137
131
|
init_esm_shims
|
|
@@ -1564,377 +1558,6 @@ Notes:
|
|
|
1564
1558
|
// src/commands/zero/connector/index.ts
|
|
1565
1559
|
init_esm_shims();
|
|
1566
1560
|
|
|
1567
|
-
// src/commands/zero/connector/connect.ts
|
|
1568
|
-
init_esm_shims();
|
|
1569
|
-
|
|
1570
|
-
// src/lib/computer/start-services.ts
|
|
1571
|
-
init_esm_shims();
|
|
1572
|
-
import { spawn } from "child_process";
|
|
1573
|
-
import { access, constants } from "fs/promises";
|
|
1574
|
-
import { createServer } from "net";
|
|
1575
|
-
import { homedir } from "os";
|
|
1576
|
-
import { join } from "path";
|
|
1577
|
-
|
|
1578
|
-
// src/lib/computer/ngrok.ts
|
|
1579
|
-
init_esm_shims();
|
|
1580
|
-
async function loadNgrok() {
|
|
1581
|
-
try {
|
|
1582
|
-
const mod = await import("@ngrok/ngrok");
|
|
1583
|
-
return mod.default;
|
|
1584
|
-
} catch (cause) {
|
|
1585
|
-
throw new Error(
|
|
1586
|
-
"Failed to load ngrok tunnel module. This may be caused by a system library (GLIBC) incompatibility. See: https://github.com/vm0-ai/vm0/issues/6825",
|
|
1587
|
-
{ cause }
|
|
1588
|
-
);
|
|
1589
|
-
}
|
|
1590
|
-
}
|
|
1591
|
-
async function startNgrokTunnels(ngrokToken, endpointPrefix, webdavPort, cdpPort) {
|
|
1592
|
-
const ngrok = await loadNgrok();
|
|
1593
|
-
await ngrok.forward({
|
|
1594
|
-
addr: `localhost:${webdavPort}`,
|
|
1595
|
-
authtoken: ngrokToken,
|
|
1596
|
-
domain: `webdav.${endpointPrefix}.internal`
|
|
1597
|
-
});
|
|
1598
|
-
await ngrok.forward({
|
|
1599
|
-
addr: `localhost:${cdpPort}`,
|
|
1600
|
-
authtoken: ngrokToken,
|
|
1601
|
-
domain: `chrome.${endpointPrefix}.internal`
|
|
1602
|
-
});
|
|
1603
|
-
}
|
|
1604
|
-
async function stopNgrokTunnels() {
|
|
1605
|
-
const ngrok = await loadNgrok();
|
|
1606
|
-
await ngrok.kill();
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
// src/lib/computer/start-services.ts
|
|
1610
|
-
var CHROME_CANDIDATES = [
|
|
1611
|
-
// macOS absolute paths
|
|
1612
|
-
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
1613
|
-
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
|
|
1614
|
-
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
1615
|
-
// Linux / PATH-based
|
|
1616
|
-
"google-chrome",
|
|
1617
|
-
"google-chrome-stable",
|
|
1618
|
-
"chromium-browser",
|
|
1619
|
-
"chromium",
|
|
1620
|
-
"chrome"
|
|
1621
|
-
];
|
|
1622
|
-
async function getRandomPort() {
|
|
1623
|
-
return new Promise((resolve, reject) => {
|
|
1624
|
-
const server = createServer();
|
|
1625
|
-
server.listen(0, "127.0.0.1", () => {
|
|
1626
|
-
const { port } = server.address();
|
|
1627
|
-
server.close(() => {
|
|
1628
|
-
return resolve(port);
|
|
1629
|
-
});
|
|
1630
|
-
});
|
|
1631
|
-
server.on("error", reject);
|
|
1632
|
-
});
|
|
1633
|
-
}
|
|
1634
|
-
async function findBinary(...candidates) {
|
|
1635
|
-
for (const candidate of candidates) {
|
|
1636
|
-
if (candidate.startsWith("/")) {
|
|
1637
|
-
try {
|
|
1638
|
-
await access(candidate, constants.X_OK);
|
|
1639
|
-
return candidate;
|
|
1640
|
-
} catch {
|
|
1641
|
-
}
|
|
1642
|
-
} else {
|
|
1643
|
-
const found = await new Promise((resolve) => {
|
|
1644
|
-
const child = spawn("which", [candidate]);
|
|
1645
|
-
child.on("close", (code) => {
|
|
1646
|
-
return resolve(code === 0);
|
|
1647
|
-
});
|
|
1648
|
-
});
|
|
1649
|
-
if (found) return candidate;
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
return null;
|
|
1653
|
-
}
|
|
1654
|
-
async function checkComputerDependencies() {
|
|
1655
|
-
const wsgidavBinary = await findBinary("wsgidav");
|
|
1656
|
-
if (!wsgidavBinary) {
|
|
1657
|
-
throw new Error(
|
|
1658
|
-
"wsgidav not found\n\nInstall with: pip install wsgidav[cheroot]"
|
|
1659
|
-
);
|
|
1660
|
-
}
|
|
1661
|
-
const chromeBinary = await findBinary(...CHROME_CANDIDATES);
|
|
1662
|
-
if (!chromeBinary) {
|
|
1663
|
-
throw new Error("Chrome not found\n\nInstall Google Chrome or Chromium");
|
|
1664
|
-
}
|
|
1665
|
-
}
|
|
1666
|
-
async function startComputerServices(credentials) {
|
|
1667
|
-
console.log(source_default.cyan("Starting computer connector services..."));
|
|
1668
|
-
const wsgidavBinary = await findBinary("wsgidav");
|
|
1669
|
-
if (!wsgidavBinary) {
|
|
1670
|
-
throw new Error(
|
|
1671
|
-
"wsgidav not found\n\nInstall with: pip install wsgidav[cheroot]"
|
|
1672
|
-
);
|
|
1673
|
-
}
|
|
1674
|
-
const chromeBinary = await findBinary(...CHROME_CANDIDATES);
|
|
1675
|
-
if (!chromeBinary) {
|
|
1676
|
-
throw new Error("Chrome not found\n\nInstall Google Chrome or Chromium");
|
|
1677
|
-
}
|
|
1678
|
-
const webdavPort = await getRandomPort();
|
|
1679
|
-
const cdpPort = await getRandomPort();
|
|
1680
|
-
const downloadsPath = join(homedir(), "Downloads");
|
|
1681
|
-
const wsgidav = spawn(
|
|
1682
|
-
wsgidavBinary,
|
|
1683
|
-
[
|
|
1684
|
-
"--host=127.0.0.1",
|
|
1685
|
-
`--port=${webdavPort}`,
|
|
1686
|
-
`--root=${downloadsPath}`,
|
|
1687
|
-
"--auth=anonymous",
|
|
1688
|
-
"--no-config"
|
|
1689
|
-
],
|
|
1690
|
-
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
1691
|
-
);
|
|
1692
|
-
wsgidav.stdout?.on("data", (data) => {
|
|
1693
|
-
return process.stdout.write(data);
|
|
1694
|
-
});
|
|
1695
|
-
wsgidav.stderr?.on("data", (data) => {
|
|
1696
|
-
return process.stderr.write(data);
|
|
1697
|
-
});
|
|
1698
|
-
console.log(source_default.green("\u2713 WebDAV server started"));
|
|
1699
|
-
const chrome = spawn(
|
|
1700
|
-
chromeBinary,
|
|
1701
|
-
[
|
|
1702
|
-
`--remote-debugging-port=${cdpPort}`,
|
|
1703
|
-
"--remote-debugging-address=127.0.0.1",
|
|
1704
|
-
"--headless=new",
|
|
1705
|
-
"--no-sandbox",
|
|
1706
|
-
"--disable-gpu"
|
|
1707
|
-
],
|
|
1708
|
-
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
1709
|
-
);
|
|
1710
|
-
chrome.stdout?.on("data", (data) => {
|
|
1711
|
-
return process.stdout.write(data);
|
|
1712
|
-
});
|
|
1713
|
-
chrome.stderr?.on("data", (data) => {
|
|
1714
|
-
return process.stderr.write(data);
|
|
1715
|
-
});
|
|
1716
|
-
console.log(source_default.green("\u2713 Chrome started"));
|
|
1717
|
-
try {
|
|
1718
|
-
await startNgrokTunnels(
|
|
1719
|
-
credentials.ngrokToken,
|
|
1720
|
-
credentials.endpointPrefix,
|
|
1721
|
-
webdavPort,
|
|
1722
|
-
cdpPort
|
|
1723
|
-
);
|
|
1724
|
-
console.log(
|
|
1725
|
-
source_default.green(
|
|
1726
|
-
`\u2713 ngrok tunnels: webdav.${credentials.domain}, chrome.${credentials.domain}`
|
|
1727
|
-
)
|
|
1728
|
-
);
|
|
1729
|
-
console.log();
|
|
1730
|
-
console.log(source_default.green("\u2713 Computer connector active"));
|
|
1731
|
-
console.log(` WebDAV: ~/Downloads \u2192 webdav.${credentials.domain}`);
|
|
1732
|
-
console.log(
|
|
1733
|
-
` Chrome CDP: port ${cdpPort} \u2192 chrome.${credentials.domain}`
|
|
1734
|
-
);
|
|
1735
|
-
console.log();
|
|
1736
|
-
console.log(source_default.dim("Press ^C twice to disconnect"));
|
|
1737
|
-
console.log();
|
|
1738
|
-
let sigintCount = 0;
|
|
1739
|
-
await new Promise((resolve) => {
|
|
1740
|
-
const keepAlive = setInterval(() => {
|
|
1741
|
-
}, 6e4);
|
|
1742
|
-
const done = () => {
|
|
1743
|
-
clearInterval(keepAlive);
|
|
1744
|
-
process.removeListener("SIGINT", onSigint);
|
|
1745
|
-
resolve();
|
|
1746
|
-
};
|
|
1747
|
-
const onSigint = () => {
|
|
1748
|
-
sigintCount++;
|
|
1749
|
-
if (sigintCount === 1) {
|
|
1750
|
-
console.log(source_default.dim("\nPress ^C again to disconnect and exit..."));
|
|
1751
|
-
} else {
|
|
1752
|
-
done();
|
|
1753
|
-
}
|
|
1754
|
-
};
|
|
1755
|
-
process.on("SIGINT", onSigint);
|
|
1756
|
-
process.once("SIGTERM", done);
|
|
1757
|
-
});
|
|
1758
|
-
} finally {
|
|
1759
|
-
console.log();
|
|
1760
|
-
console.log(source_default.cyan("Stopping services..."));
|
|
1761
|
-
wsgidav.kill("SIGTERM");
|
|
1762
|
-
chrome.kill("SIGTERM");
|
|
1763
|
-
await stopNgrokTunnels();
|
|
1764
|
-
console.log(source_default.green("\u2713 Services stopped"));
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
|
|
1768
|
-
// src/commands/zero/connector/connect.ts
|
|
1769
|
-
function delay(ms) {
|
|
1770
|
-
return new Promise((resolve) => {
|
|
1771
|
-
return setTimeout(resolve, ms);
|
|
1772
|
-
});
|
|
1773
|
-
}
|
|
1774
|
-
function renderHelpText(text) {
|
|
1775
|
-
return text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, label, url) => {
|
|
1776
|
-
return `${label} (${source_default.cyan(url)})`;
|
|
1777
|
-
}).replace(/\*\*([^*]+)\*\*/g, (_m, content) => {
|
|
1778
|
-
return source_default.bold(content);
|
|
1779
|
-
}).replace(/^> (.+)$/gm, (_m, content) => {
|
|
1780
|
-
return source_default.yellow(` ${content}`);
|
|
1781
|
-
});
|
|
1782
|
-
}
|
|
1783
|
-
async function connectViaApiToken(connectorType, tokenValue) {
|
|
1784
|
-
const config = CONNECTOR_TYPES[connectorType];
|
|
1785
|
-
const apiTokenConfig = config.authMethods["api-token"];
|
|
1786
|
-
if (!apiTokenConfig) {
|
|
1787
|
-
throw new Error(
|
|
1788
|
-
`${config.label} does not support API token authentication`
|
|
1789
|
-
);
|
|
1790
|
-
}
|
|
1791
|
-
const secretEntries = Object.entries(apiTokenConfig.secrets);
|
|
1792
|
-
const inputSecrets = {};
|
|
1793
|
-
if (tokenValue && secretEntries.length === 1) {
|
|
1794
|
-
const [secretName] = secretEntries[0];
|
|
1795
|
-
inputSecrets[secretName] = tokenValue;
|
|
1796
|
-
} else {
|
|
1797
|
-
if (apiTokenConfig.helpText) {
|
|
1798
|
-
console.log();
|
|
1799
|
-
console.log(renderHelpText(apiTokenConfig.helpText));
|
|
1800
|
-
console.log();
|
|
1801
|
-
}
|
|
1802
|
-
for (const [secretName, secretConfig] of secretEntries) {
|
|
1803
|
-
if (!secretConfig.required) continue;
|
|
1804
|
-
const value = await promptPassword(
|
|
1805
|
-
`${secretConfig.label}${secretConfig.placeholder ? source_default.dim(` (${secretConfig.placeholder})`) : ""}:`
|
|
1806
|
-
);
|
|
1807
|
-
if (!value) {
|
|
1808
|
-
console.log(source_default.dim("Cancelled"));
|
|
1809
|
-
return;
|
|
1810
|
-
}
|
|
1811
|
-
inputSecrets[secretName] = value;
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
for (const [name, value] of Object.entries(inputSecrets)) {
|
|
1815
|
-
await setZeroSecret({
|
|
1816
|
-
name,
|
|
1817
|
-
value,
|
|
1818
|
-
description: `API token for ${config.label} connector`
|
|
1819
|
-
});
|
|
1820
|
-
}
|
|
1821
|
-
console.log(source_default.green(`
|
|
1822
|
-
\u2713 Connector "${connectorType}" connected`));
|
|
1823
|
-
}
|
|
1824
|
-
async function connectComputer() {
|
|
1825
|
-
await checkComputerDependencies();
|
|
1826
|
-
console.log(source_default.cyan("Setting up computer connector..."));
|
|
1827
|
-
const credentials = await createZeroComputerConnector();
|
|
1828
|
-
await startComputerServices(credentials);
|
|
1829
|
-
console.log(source_default.cyan("Disconnecting computer connector..."));
|
|
1830
|
-
await deleteZeroComputerConnector();
|
|
1831
|
-
console.log(source_default.green("\u2713 Disconnected computer"));
|
|
1832
|
-
}
|
|
1833
|
-
async function resolveAuthMethod(connectorType, tokenFlag) {
|
|
1834
|
-
const config = CONNECTOR_TYPES[connectorType];
|
|
1835
|
-
const oauthFlag = CONNECTOR_TYPES[connectorType].featureFlag;
|
|
1836
|
-
const orgId = await getActiveOrg();
|
|
1837
|
-
const oauthAvailable = "oauth" in config.authMethods && (!oauthFlag || isFeatureEnabled(oauthFlag, { orgId }));
|
|
1838
|
-
const apiTokenAvailable = "api-token" in config.authMethods;
|
|
1839
|
-
if (tokenFlag) {
|
|
1840
|
-
if (!apiTokenAvailable) {
|
|
1841
|
-
throw new Error(
|
|
1842
|
-
`${config.label} does not support API token authentication`
|
|
1843
|
-
);
|
|
1844
|
-
}
|
|
1845
|
-
return "api-token";
|
|
1846
|
-
}
|
|
1847
|
-
if (oauthAvailable && apiTokenAvailable) {
|
|
1848
|
-
const selected = await promptSelect(
|
|
1849
|
-
`How would you like to connect ${config.label}?`,
|
|
1850
|
-
[
|
|
1851
|
-
{ title: "OAuth (Sign in with browser)", value: "oauth" },
|
|
1852
|
-
{
|
|
1853
|
-
title: `API Token (${config.authMethods["api-token"].label})`,
|
|
1854
|
-
value: "api-token"
|
|
1855
|
-
}
|
|
1856
|
-
]
|
|
1857
|
-
);
|
|
1858
|
-
if (!selected) {
|
|
1859
|
-
console.log(source_default.dim("Cancelled"));
|
|
1860
|
-
return null;
|
|
1861
|
-
}
|
|
1862
|
-
return selected;
|
|
1863
|
-
}
|
|
1864
|
-
if (apiTokenAvailable) return "api-token";
|
|
1865
|
-
if (oauthAvailable) return "oauth";
|
|
1866
|
-
throw new Error(
|
|
1867
|
-
`${config.label} has no available auth methods. OAuth may not be enabled yet.`
|
|
1868
|
-
);
|
|
1869
|
-
}
|
|
1870
|
-
async function connectViaOAuth(connectorType) {
|
|
1871
|
-
console.log(`Connecting ${source_default.cyan(connectorType)}...`);
|
|
1872
|
-
const session = await createZeroConnectorSession(connectorType);
|
|
1873
|
-
const apiUrl = await getBaseUrl();
|
|
1874
|
-
const verificationUrl = `${apiUrl}${session.verificationUrl}`;
|
|
1875
|
-
console.log(source_default.green("\nSession created"));
|
|
1876
|
-
console.log(source_default.cyan(`
|
|
1877
|
-
To connect, visit: ${verificationUrl}`));
|
|
1878
|
-
console.log(
|
|
1879
|
-
`
|
|
1880
|
-
The session expires in ${Math.floor(session.expiresIn / 60)} minutes.`
|
|
1881
|
-
);
|
|
1882
|
-
console.log("\nWaiting for authorization...");
|
|
1883
|
-
const startTime = Date.now();
|
|
1884
|
-
const maxWaitTime = session.expiresIn * 1e3;
|
|
1885
|
-
const pollInterval = (session.interval || 5) * 1e3;
|
|
1886
|
-
let isFirstPoll = true;
|
|
1887
|
-
while (Date.now() - startTime < maxWaitTime) {
|
|
1888
|
-
if (!isFirstPoll) {
|
|
1889
|
-
await delay(pollInterval);
|
|
1890
|
-
}
|
|
1891
|
-
isFirstPoll = false;
|
|
1892
|
-
const status = await getZeroConnectorSession(connectorType, session.id);
|
|
1893
|
-
switch (status.status) {
|
|
1894
|
-
case "complete":
|
|
1895
|
-
console.log(
|
|
1896
|
-
source_default.green(`
|
|
1897
|
-
|
|
1898
|
-
\u2713 Connector "${connectorType}" connected`)
|
|
1899
|
-
);
|
|
1900
|
-
return;
|
|
1901
|
-
case "expired":
|
|
1902
|
-
throw new Error("Session expired, please try again");
|
|
1903
|
-
case "error":
|
|
1904
|
-
throw new Error(
|
|
1905
|
-
`Connection failed: ${status.errorMessage || "Unknown error"}`
|
|
1906
|
-
);
|
|
1907
|
-
case "pending":
|
|
1908
|
-
process.stdout.write(source_default.dim("."));
|
|
1909
|
-
break;
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
throw new Error("Session timed out, please try again");
|
|
1913
|
-
}
|
|
1914
|
-
var connectCommand = new Command().name("connect").description("Connect a third-party service (e.g., GitHub)").argument("<type>", "Connector type (e.g., github)").option("--token <value>", "API token value (skip interactive prompt)").action(
|
|
1915
|
-
withErrorHandler(async (type, options) => {
|
|
1916
|
-
const parseResult = connectorTypeSchema.safeParse(type);
|
|
1917
|
-
if (!parseResult.success) {
|
|
1918
|
-
const available = Object.keys(CONNECTOR_TYPES).join(", ");
|
|
1919
|
-
throw new Error(`Unknown connector type: ${type}`, {
|
|
1920
|
-
cause: new Error(`Available connectors: ${available}`)
|
|
1921
|
-
});
|
|
1922
|
-
}
|
|
1923
|
-
const connectorType = parseResult.data;
|
|
1924
|
-
if (connectorType === "computer") {
|
|
1925
|
-
await connectComputer();
|
|
1926
|
-
return;
|
|
1927
|
-
}
|
|
1928
|
-
const authMethod = await resolveAuthMethod(connectorType, options.token);
|
|
1929
|
-
if (!authMethod) return;
|
|
1930
|
-
if (authMethod === "api-token") {
|
|
1931
|
-
await connectViaApiToken(connectorType, options.token);
|
|
1932
|
-
return;
|
|
1933
|
-
}
|
|
1934
|
-
await connectViaOAuth(connectorType);
|
|
1935
|
-
})
|
|
1936
|
-
);
|
|
1937
|
-
|
|
1938
1561
|
// src/commands/zero/connector/list.ts
|
|
1939
1562
|
init_esm_shims();
|
|
1940
1563
|
var listCommand6 = new Command().name("list").alias("ls").description("List all connectors and their status").action(
|
|
@@ -1978,9 +1601,6 @@ var listCommand6 = new Command().name("list").alias("ls").description("List all
|
|
|
1978
1601
|
const row = [type.padEnd(typeWidth), status, account].join(" ");
|
|
1979
1602
|
console.log(row);
|
|
1980
1603
|
}
|
|
1981
|
-
console.log();
|
|
1982
|
-
console.log(source_default.dim("To connect a service:"));
|
|
1983
|
-
console.log(source_default.dim(" zero connector connect <type>"));
|
|
1984
1604
|
})
|
|
1985
1605
|
);
|
|
1986
1606
|
|
|
@@ -2154,39 +1774,16 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
|
|
|
2154
1774
|
`${"Last Updated:".padEnd(LABEL_WIDTH)}${formatDateTime(connector.updatedAt)}`
|
|
2155
1775
|
);
|
|
2156
1776
|
}
|
|
2157
|
-
console.log();
|
|
2158
|
-
console.log(source_default.dim("To disconnect:"));
|
|
2159
|
-
console.log(source_default.dim(` zero connector disconnect ${type}`));
|
|
2160
1777
|
} else {
|
|
2161
1778
|
console.log(
|
|
2162
1779
|
`${"Status:".padEnd(LABEL_WIDTH)}${source_default.dim("not connected")}`
|
|
2163
1780
|
);
|
|
2164
|
-
console.log();
|
|
2165
|
-
console.log(source_default.dim("To connect:"));
|
|
2166
|
-
console.log(source_default.dim(` zero connector connect ${type}`));
|
|
2167
1781
|
}
|
|
2168
1782
|
})
|
|
2169
1783
|
);
|
|
2170
1784
|
|
|
2171
|
-
// src/commands/zero/connector/disconnect.ts
|
|
2172
|
-
init_esm_shims();
|
|
2173
|
-
var disconnectCommand = new Command().name("disconnect").description("Disconnect a third-party service").argument("<type>", "Connector type to disconnect (e.g., github)").action(
|
|
2174
|
-
withErrorHandler(async (type) => {
|
|
2175
|
-
const parseResult = connectorTypeSchema.safeParse(type);
|
|
2176
|
-
if (!parseResult.success) {
|
|
2177
|
-
const available = Object.keys(CONNECTOR_TYPES).join(", ");
|
|
2178
|
-
throw new Error(`Unknown connector type: ${type}`, {
|
|
2179
|
-
cause: new Error(`Available connectors: ${available}`)
|
|
2180
|
-
});
|
|
2181
|
-
}
|
|
2182
|
-
const connectorType = parseResult.data;
|
|
2183
|
-
await deleteZeroConnector(connectorType);
|
|
2184
|
-
console.log(source_default.green(`\u2713 Disconnected ${type}`));
|
|
2185
|
-
})
|
|
2186
|
-
);
|
|
2187
|
-
|
|
2188
1785
|
// src/commands/zero/connector/index.ts
|
|
2189
|
-
var zeroConnectorCommand = new Command().name("connector").description("Check
|
|
1786
|
+
var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(listCommand6).addCommand(statusCommand2);
|
|
2190
1787
|
|
|
2191
1788
|
// src/commands/zero/doctor/index.ts
|
|
2192
1789
|
init_esm_shims();
|
|
@@ -4222,10 +3819,10 @@ Notes:
|
|
|
4222
3819
|
|
|
4223
3820
|
// src/commands/zero/slack/download-file.ts
|
|
4224
3821
|
init_esm_shims();
|
|
4225
|
-
import { join
|
|
3822
|
+
import { join } from "path";
|
|
4226
3823
|
import { tmpdir } from "os";
|
|
4227
3824
|
function defaultOutPath(fileId) {
|
|
4228
|
-
return
|
|
3825
|
+
return join(tmpdir(), `slack-${fileId}`);
|
|
4229
3826
|
}
|
|
4230
3827
|
var downloadFileCommand = new Command().name("download-file").description("Download a Slack file by id using the bot token").argument("<file-id>", "Slack file id (e.g. F01234ABCD)").option(
|
|
4231
3828
|
"-o, --out <path>",
|
|
@@ -4520,7 +4117,7 @@ init_esm_shims();
|
|
|
4520
4117
|
// src/lib/skill-directory.ts
|
|
4521
4118
|
init_esm_shims();
|
|
4522
4119
|
import { readFileSync as readFileSync6, readdirSync } from "fs";
|
|
4523
|
-
import { join as
|
|
4120
|
+
import { join as join2 } from "path";
|
|
4524
4121
|
var IGNORED_NAMES = /* @__PURE__ */ new Set(["node_modules", ".git", ".DS_Store"]);
|
|
4525
4122
|
function readSkillDirectory(dirPath) {
|
|
4526
4123
|
const files = [];
|
|
@@ -4530,11 +4127,11 @@ function readSkillDirectory(dirPath) {
|
|
|
4530
4127
|
if (entry.name.startsWith(".") || IGNORED_NAMES.has(entry.name)) continue;
|
|
4531
4128
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
4532
4129
|
if (entry.isDirectory()) {
|
|
4533
|
-
walk(
|
|
4130
|
+
walk(join2(dir, entry.name), relPath);
|
|
4534
4131
|
} else {
|
|
4535
4132
|
files.push({
|
|
4536
4133
|
path: relPath,
|
|
4537
|
-
content: readFileSync6(
|
|
4134
|
+
content: readFileSync6(join2(dir, entry.name), "utf-8")
|
|
4538
4135
|
});
|
|
4539
4136
|
}
|
|
4540
4137
|
}
|
|
@@ -5117,7 +4714,7 @@ init_esm_shims();
|
|
|
5117
4714
|
// src/lib/computer-use/desktop-server.ts
|
|
5118
4715
|
init_esm_shims();
|
|
5119
4716
|
import {
|
|
5120
|
-
createServer
|
|
4717
|
+
createServer
|
|
5121
4718
|
} from "http";
|
|
5122
4719
|
import { createServer as createNetServer } from "net";
|
|
5123
4720
|
|
|
@@ -5126,12 +4723,12 @@ init_esm_shims();
|
|
|
5126
4723
|
import { execFile } from "child_process";
|
|
5127
4724
|
import { readFile, unlink } from "fs/promises";
|
|
5128
4725
|
import { randomUUID } from "crypto";
|
|
5129
|
-
import { join as
|
|
4726
|
+
import { join as join3 } from "path";
|
|
5130
4727
|
import { tmpdir as tmpdir2 } from "os";
|
|
5131
4728
|
import { promisify } from "util";
|
|
5132
4729
|
var execFileAsync = promisify(execFile);
|
|
5133
4730
|
async function captureScreenshot() {
|
|
5134
|
-
const tmpPath =
|
|
4731
|
+
const tmpPath = join3(tmpdir2(), `vm0-screenshot-${randomUUID()}.jpg`);
|
|
5135
4732
|
try {
|
|
5136
4733
|
await execFileAsync("screencapture", ["-x", "-t", "jpg", tmpPath]);
|
|
5137
4734
|
const info = await getScreenInfo();
|
|
@@ -5160,7 +4757,7 @@ async function captureScreenshot() {
|
|
|
5160
4757
|
}
|
|
5161
4758
|
}
|
|
5162
4759
|
async function captureRegionScreenshot(region) {
|
|
5163
|
-
const tmpPath =
|
|
4760
|
+
const tmpPath = join3(tmpdir2(), `vm0-zoom-${randomUUID()}.jpg`);
|
|
5164
4761
|
try {
|
|
5165
4762
|
const regionArg = `${region.x},${region.y},${region.width},${region.height}`;
|
|
5166
4763
|
await execFileAsync("screencapture", [
|
|
@@ -5417,7 +5014,7 @@ async function scroll(x, y, direction, amount = DEFAULT_SCROLL_AMOUNT) {
|
|
|
5417
5014
|
|
|
5418
5015
|
// src/lib/computer-use/clipboard.ts
|
|
5419
5016
|
init_esm_shims();
|
|
5420
|
-
import { execFile as execFile4, spawn
|
|
5017
|
+
import { execFile as execFile4, spawn } from "child_process";
|
|
5421
5018
|
import { promisify as promisify4 } from "util";
|
|
5422
5019
|
var execFileAsync4 = promisify4(execFile4);
|
|
5423
5020
|
async function readClipboard() {
|
|
@@ -5426,7 +5023,7 @@ async function readClipboard() {
|
|
|
5426
5023
|
}
|
|
5427
5024
|
async function writeClipboard(text) {
|
|
5428
5025
|
return new Promise((resolve, reject) => {
|
|
5429
|
-
const proc =
|
|
5026
|
+
const proc = spawn("pbcopy", { stdio: ["pipe", "ignore", "ignore"] });
|
|
5430
5027
|
proc.on("error", reject);
|
|
5431
5028
|
proc.on("close", (code) => {
|
|
5432
5029
|
if (code === 0) {
|
|
@@ -5653,7 +5250,7 @@ async function handleOpenApplication(req, res) {
|
|
|
5653
5250
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
5654
5251
|
res.end(JSON.stringify({ ok: true }));
|
|
5655
5252
|
}
|
|
5656
|
-
async function
|
|
5253
|
+
async function getRandomPort() {
|
|
5657
5254
|
return new Promise((resolve, reject) => {
|
|
5658
5255
|
const server = createNetServer();
|
|
5659
5256
|
server.listen(0, "127.0.0.1", () => {
|
|
@@ -5727,7 +5324,7 @@ async function handleRequest(token, req, res) {
|
|
|
5727
5324
|
}
|
|
5728
5325
|
function startDesktopServer(token, port) {
|
|
5729
5326
|
return new Promise((resolve, reject) => {
|
|
5730
|
-
const server =
|
|
5327
|
+
const server = createServer((req, res) => {
|
|
5731
5328
|
handleRequest(token, req, res).catch(() => {
|
|
5732
5329
|
if (!res.headersSent) {
|
|
5733
5330
|
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
@@ -5744,7 +5341,7 @@ function startDesktopServer(token, port) {
|
|
|
5744
5341
|
|
|
5745
5342
|
// src/lib/computer-use/ngrok.ts
|
|
5746
5343
|
init_esm_shims();
|
|
5747
|
-
async function
|
|
5344
|
+
async function loadNgrok() {
|
|
5748
5345
|
try {
|
|
5749
5346
|
const mod = await import("@ngrok/ngrok");
|
|
5750
5347
|
return mod.default;
|
|
@@ -5756,7 +5353,7 @@ async function loadNgrok2() {
|
|
|
5756
5353
|
}
|
|
5757
5354
|
}
|
|
5758
5355
|
async function startDesktopTunnel(ngrokToken, endpointPrefix, port) {
|
|
5759
|
-
const ngrok = await
|
|
5356
|
+
const ngrok = await loadNgrok();
|
|
5760
5357
|
await ngrok.forward({
|
|
5761
5358
|
addr: `localhost:${port}`,
|
|
5762
5359
|
authtoken: ngrokToken,
|
|
@@ -5764,7 +5361,7 @@ async function startDesktopTunnel(ngrokToken, endpointPrefix, port) {
|
|
|
5764
5361
|
});
|
|
5765
5362
|
}
|
|
5766
5363
|
async function stopDesktopTunnel() {
|
|
5767
|
-
const ngrok = await
|
|
5364
|
+
const ngrok = await loadNgrok();
|
|
5768
5365
|
await ngrok.kill();
|
|
5769
5366
|
}
|
|
5770
5367
|
|
|
@@ -5786,7 +5383,7 @@ var hostStartCommand = new Command().name("start").description("Start the comput
|
|
|
5786
5383
|
}
|
|
5787
5384
|
console.log(source_default.cyan("Registering computer-use host..."));
|
|
5788
5385
|
const credentials = await registerComputerUseHost();
|
|
5789
|
-
const port = await
|
|
5386
|
+
const port = await getRandomPort();
|
|
5790
5387
|
const server = await startDesktopServer(credentials.token, port);
|
|
5791
5388
|
try {
|
|
5792
5389
|
await startDesktopTunnel(
|
|
@@ -5852,7 +5449,7 @@ var hostStopCommand = new Command().name("stop").description("Stop and unregiste
|
|
|
5852
5449
|
// src/commands/zero/computer-use/client.ts
|
|
5853
5450
|
init_esm_shims();
|
|
5854
5451
|
import { writeFile, mkdir } from "fs/promises";
|
|
5855
|
-
import { join as
|
|
5452
|
+
import { join as join4 } from "path";
|
|
5856
5453
|
|
|
5857
5454
|
// src/lib/computer-use/client.ts
|
|
5858
5455
|
init_esm_shims();
|
|
@@ -5920,7 +5517,7 @@ var clientScreenshotCommand = new Command().name("screenshot").description("Capt
|
|
|
5920
5517
|
const dir = "/tmp/computer-use";
|
|
5921
5518
|
await mkdir(dir, { recursive: true });
|
|
5922
5519
|
const timestamp = Date.now();
|
|
5923
|
-
const filePath =
|
|
5520
|
+
const filePath = join4(dir, `screenshot-${timestamp}.${data.format}`);
|
|
5924
5521
|
const buffer = Buffer.from(data.image, "base64");
|
|
5925
5522
|
await writeFile(filePath, buffer);
|
|
5926
5523
|
process.stdout.write(`${filePath}
|
|
@@ -5948,7 +5545,7 @@ var clientZoomCommand = new Command().name("zoom").description("Capture a region
|
|
|
5948
5545
|
const dir = "/tmp/computer-use";
|
|
5949
5546
|
await mkdir(dir, { recursive: true });
|
|
5950
5547
|
const timestamp = Date.now();
|
|
5951
|
-
const filePath =
|
|
5548
|
+
const filePath = join4(dir, `zoom-${timestamp}.${data.format}`);
|
|
5952
5549
|
const buffer = Buffer.from(data.image, "base64");
|
|
5953
5550
|
await writeFile(filePath, buffer);
|
|
5954
5551
|
process.stdout.write(`${filePath}
|
|
@@ -6172,7 +5769,7 @@ function printCallInfo(call, callId) {
|
|
|
6172
5769
|
// src/commands/zero/phone/call.ts
|
|
6173
5770
|
var POLL_INTERVAL_MS = 1e4;
|
|
6174
5771
|
var POLL_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
6175
|
-
var
|
|
5772
|
+
var delay = {
|
|
6176
5773
|
ms: (ms) => {
|
|
6177
5774
|
return new Promise((resolve) => {
|
|
6178
5775
|
setTimeout(resolve, ms);
|
|
@@ -6243,7 +5840,7 @@ var callCommand = new Command().name("call").description("Initiate an outbound p
|
|
|
6243
5840
|
);
|
|
6244
5841
|
const startTime = Date.now();
|
|
6245
5842
|
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
6246
|
-
await
|
|
5843
|
+
await delay.ms(POLL_INTERVAL_MS);
|
|
6247
5844
|
const detail = await getPhoneCallDetail(result.callId);
|
|
6248
5845
|
const status = detail.call.status;
|
|
6249
5846
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
@@ -6422,10 +6019,10 @@ init_esm_shims();
|
|
|
6422
6019
|
|
|
6423
6020
|
// src/commands/zero/web/download-file.ts
|
|
6424
6021
|
init_esm_shims();
|
|
6425
|
-
import { join as
|
|
6022
|
+
import { join as join5 } from "path";
|
|
6426
6023
|
import { tmpdir as tmpdir3 } from "os";
|
|
6427
6024
|
function defaultOutPath2(fileId) {
|
|
6428
|
-
return
|
|
6025
|
+
return join5(tmpdir3(), `web-${fileId}`);
|
|
6429
6026
|
}
|
|
6430
6027
|
var downloadFileCommand2 = new Command().name("download-file").description("Download a web-uploaded file by id").argument("<file-id>", "File id (UUID returned by the upload API)").option(
|
|
6431
6028
|
"-o, --out <path>",
|
|
@@ -6523,7 +6120,7 @@ function registerZeroCommands(prog, commands) {
|
|
|
6523
6120
|
var program = new Command();
|
|
6524
6121
|
program.name("zero").description(
|
|
6525
6122
|
"Zero CLI \u2014 interact with the zero platform from inside the sandbox"
|
|
6526
|
-
).version("9.119.
|
|
6123
|
+
).version("9.119.3").addHelpText(
|
|
6527
6124
|
"after",
|
|
6528
6125
|
`
|
|
6529
6126
|
Examples:
|