aicomputer 0.1.7 → 0.1.8
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 +75 -40
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1537,7 +1537,7 @@ var CLAUDE_OAUTH_REDIRECT_URL = process.env.CLAUDE_OAUTH_REDIRECT_URL ?? "https:
|
|
|
1537
1537
|
var CLAUDE_OAUTH_SCOPES = (process.env.CLAUDE_OAUTH_SCOPES ?? "user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload").split(/\s+/).filter(Boolean);
|
|
1538
1538
|
var readyPollIntervalMs = 2e3;
|
|
1539
1539
|
var readyPollTimeoutMs = 18e4;
|
|
1540
|
-
var claudeAuthCommand = new Command4("claude-auth").alias("claude-login").description("Authenticate Claude Code on a computer").option("--machine <id-or-handle>", "Use a specific computer").option("--keep-helper", "Keep a temporary helper machine if one is created").option("--skip-cross-check", "Skip verification on a second shared machine").action(async (options) => {
|
|
1540
|
+
var claudeAuthCommand = new Command4("claude-auth").alias("claude-login").description("Authenticate Claude Code on a computer").option("--machine <id-or-handle>", "Use a specific computer").option("--keep-helper", "Keep a temporary helper machine if one is created").option("--skip-cross-check", "Skip verification on a second shared machine").option("--verbose", "Show step-by-step auth diagnostics").action(async (options) => {
|
|
1541
1541
|
const todos = createTodoList();
|
|
1542
1542
|
let target = null;
|
|
1543
1543
|
let helperCreated = false;
|
|
@@ -1573,19 +1573,22 @@ var claudeAuthCommand = new Command4("claude-auth").alias("claude-login").descri
|
|
|
1573
1573
|
sharedInstall ? `installed Claude login on shared home via ${target.handle}` : `installed Claude login on ${target.handle}`
|
|
1574
1574
|
);
|
|
1575
1575
|
activeTodoID = "verify-primary";
|
|
1576
|
-
await verifyStoredAuth(sshTarget);
|
|
1577
|
-
|
|
1576
|
+
const primaryVerification = await verifyStoredAuth(sshTarget);
|
|
1577
|
+
markVerificationTodo(
|
|
1578
1578
|
todos,
|
|
1579
1579
|
"verify-primary",
|
|
1580
|
-
|
|
1580
|
+
primaryVerification,
|
|
1581
1581
|
`${target.handle} fresh login shell sees Claude auth`
|
|
1582
1582
|
);
|
|
1583
1583
|
activeTodoID = "verify-shared";
|
|
1584
|
-
const sharedCheck = await verifySecondaryMachine(
|
|
1584
|
+
const sharedCheck = primaryVerification.status === "verified" ? await verifySecondaryMachine(
|
|
1585
1585
|
target.id,
|
|
1586
1586
|
sharedInstall,
|
|
1587
1587
|
Boolean(options.skipCrossCheck)
|
|
1588
|
-
)
|
|
1588
|
+
) : {
|
|
1589
|
+
status: "skipped",
|
|
1590
|
+
reason: "primary verification was inconclusive"
|
|
1591
|
+
};
|
|
1589
1592
|
if (sharedCheck.status === "verified") {
|
|
1590
1593
|
markTodo(
|
|
1591
1594
|
todos,
|
|
@@ -1623,7 +1626,9 @@ var claudeAuthCommand = new Command4("claude-auth").alias("claude-login").descri
|
|
|
1623
1626
|
} else {
|
|
1624
1627
|
markTodo(todos, "cleanup", "skipped", "no helper created");
|
|
1625
1628
|
}
|
|
1626
|
-
|
|
1629
|
+
if (options.verbose) {
|
|
1630
|
+
printTodoList(todos);
|
|
1631
|
+
}
|
|
1627
1632
|
}
|
|
1628
1633
|
if (failureMessage) {
|
|
1629
1634
|
console.error(chalk5.red(`
|
|
@@ -1631,7 +1636,9 @@ ${failureMessage}`));
|
|
|
1631
1636
|
process.exit(1);
|
|
1632
1637
|
}
|
|
1633
1638
|
if (target) {
|
|
1634
|
-
console.log(
|
|
1639
|
+
console.log(
|
|
1640
|
+
chalk5.green(`Claude login installed on ${chalk5.bold(target.handle)}.`)
|
|
1641
|
+
);
|
|
1635
1642
|
console.log();
|
|
1636
1643
|
}
|
|
1637
1644
|
});
|
|
@@ -1654,6 +1661,13 @@ function markTodo(items, id, state, detail) {
|
|
|
1654
1661
|
item.state = state;
|
|
1655
1662
|
item.detail = detail;
|
|
1656
1663
|
}
|
|
1664
|
+
function markVerificationTodo(items, id, result, successDetail) {
|
|
1665
|
+
if (result.status === "verified") {
|
|
1666
|
+
markTodo(items, id, "done", successDetail);
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
1669
|
+
markTodo(items, id, "skipped", result.detail);
|
|
1670
|
+
}
|
|
1657
1671
|
function printTodoList(items) {
|
|
1658
1672
|
console.log();
|
|
1659
1673
|
console.log(chalk5.dim("TODO"));
|
|
@@ -1889,7 +1903,7 @@ async function installClaudeAuth(target, oauth) {
|
|
|
1889
1903
|
const spinner = ora3(`Installing Claude auth on ${chalk5.bold(target.handle)}...`).start();
|
|
1890
1904
|
try {
|
|
1891
1905
|
const installScript = buildInstallScript(oauth.refreshToken, oauth.scope);
|
|
1892
|
-
const result = await
|
|
1906
|
+
const result = await runRemoteCommand(target, ["bash", "-s"], installScript);
|
|
1893
1907
|
if (result.stdout.trim()) {
|
|
1894
1908
|
spinner.succeed(`Installed Claude auth on ${chalk5.bold(target.handle)}`);
|
|
1895
1909
|
return;
|
|
@@ -1922,32 +1936,53 @@ function buildInstallScript(refreshToken, scopes) {
|
|
|
1922
1936
|
].join("\n");
|
|
1923
1937
|
}
|
|
1924
1938
|
async function verifyStoredAuth(target) {
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1939
|
+
try {
|
|
1940
|
+
const result = await runRemoteCommand(target, [
|
|
1941
|
+
"bash",
|
|
1942
|
+
"--noprofile",
|
|
1943
|
+
"--norc",
|
|
1944
|
+
"-lc",
|
|
1945
|
+
"claude auth status --json 2>/dev/null || claude auth status"
|
|
1946
|
+
]);
|
|
1947
|
+
const payload = parseStatusOutput(result.stdout, result.stderr);
|
|
1948
|
+
if (payload.loggedIn) {
|
|
1949
|
+
return { status: "verified", detail: "verified" };
|
|
1950
|
+
}
|
|
1951
|
+
return {
|
|
1952
|
+
status: "failed",
|
|
1953
|
+
detail: payload.detail ? `verification failed: ${payload.detail}` : "verification failed"
|
|
1954
|
+
};
|
|
1955
|
+
} catch (error) {
|
|
1956
|
+
return {
|
|
1957
|
+
status: "inconclusive",
|
|
1958
|
+
detail: error instanceof Error ? error.message : "verification command did not complete cleanly"
|
|
1959
|
+
};
|
|
1930
1960
|
}
|
|
1931
1961
|
}
|
|
1932
|
-
function
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
'USER="${USER:-node}"',
|
|
1937
|
-
'SHELL="/bin/bash"',
|
|
1938
|
-
'PATH="$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin"',
|
|
1939
|
-
"bash -lc",
|
|
1940
|
-
shellQuote(inner)
|
|
1941
|
-
].join(" ");
|
|
1942
|
-
}
|
|
1943
|
-
function parseStatusOutput(stdout) {
|
|
1944
|
-
const start = stdout.indexOf("{");
|
|
1945
|
-
const end = stdout.lastIndexOf("}");
|
|
1962
|
+
function parseStatusOutput(stdout, stderr) {
|
|
1963
|
+
const combined = [stdout, stderr].map((value) => value.trim()).filter(Boolean).join("\n");
|
|
1964
|
+
const start = combined.indexOf("{");
|
|
1965
|
+
const end = combined.lastIndexOf("}");
|
|
1946
1966
|
if (start === -1 || end === -1 || end <= start) {
|
|
1947
|
-
|
|
1967
|
+
const normalized = combined.toLowerCase();
|
|
1968
|
+
if (normalized.includes("logged in")) {
|
|
1969
|
+
return { loggedIn: true };
|
|
1970
|
+
}
|
|
1971
|
+
if (normalized.includes("not logged in") || normalized.includes("logged out")) {
|
|
1972
|
+
return { loggedIn: false, detail: firstStatusLine(combined) };
|
|
1973
|
+
}
|
|
1974
|
+
throw new Error(
|
|
1975
|
+
combined ? `could not verify Claude auth from status output: ${firstStatusLine(combined)}` : "could not verify Claude auth from empty status output"
|
|
1976
|
+
);
|
|
1948
1977
|
}
|
|
1949
|
-
const parsed = JSON.parse(
|
|
1950
|
-
return {
|
|
1978
|
+
const parsed = JSON.parse(combined.slice(start, end + 1));
|
|
1979
|
+
return {
|
|
1980
|
+
loggedIn: parsed.loggedIn === true,
|
|
1981
|
+
detail: parsed.loggedIn === true ? void 0 : parsed.error
|
|
1982
|
+
};
|
|
1983
|
+
}
|
|
1984
|
+
function firstStatusLine(value) {
|
|
1985
|
+
return value.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "unknown output";
|
|
1951
1986
|
}
|
|
1952
1987
|
async function verifySecondaryMachine(primaryComputerID, sharedInstall, skip) {
|
|
1953
1988
|
if (!sharedInstall) {
|
|
@@ -1968,10 +2003,13 @@ async function verifySecondaryMachine(primaryComputerID, sharedInstall, skip) {
|
|
|
1968
2003
|
};
|
|
1969
2004
|
}
|
|
1970
2005
|
const sshTarget = await resolveSSHTarget(secondary);
|
|
1971
|
-
await verifyStoredAuth(sshTarget);
|
|
2006
|
+
const verification = await verifyStoredAuth(sshTarget);
|
|
2007
|
+
if (verification.status !== "verified") {
|
|
2008
|
+
return { status: "skipped", reason: verification.detail };
|
|
2009
|
+
}
|
|
1972
2010
|
return { status: "verified", handle: secondary.handle };
|
|
1973
2011
|
}
|
|
1974
|
-
async function
|
|
2012
|
+
async function runRemoteCommand(target, remoteArgs, script) {
|
|
1975
2013
|
const args = [
|
|
1976
2014
|
"-T",
|
|
1977
2015
|
"-i",
|
|
@@ -1979,8 +2017,7 @@ async function runRemoteBash(target, bashArgs, script) {
|
|
|
1979
2017
|
"-p",
|
|
1980
2018
|
String(target.port),
|
|
1981
2019
|
`${target.user}@${target.host}`,
|
|
1982
|
-
|
|
1983
|
-
...bashArgs
|
|
2020
|
+
...remoteArgs
|
|
1984
2021
|
];
|
|
1985
2022
|
return new Promise((resolve, reject) => {
|
|
1986
2023
|
const child = spawn2("ssh", args, {
|
|
@@ -2010,9 +2047,6 @@ async function runRemoteBash(target, bashArgs, script) {
|
|
|
2010
2047
|
}
|
|
2011
2048
|
});
|
|
2012
2049
|
}
|
|
2013
|
-
function shellQuote(value) {
|
|
2014
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
2015
|
-
}
|
|
2016
2050
|
function base64url(buffer) {
|
|
2017
2051
|
return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
2018
2052
|
}
|
|
@@ -2582,7 +2616,8 @@ _computer() {
|
|
|
2582
2616
|
_arguments \\
|
|
2583
2617
|
'--machine[Use a specific computer]:computer:_computer_handles' \\
|
|
2584
2618
|
'--keep-helper[Keep a temporary helper machine]' \\
|
|
2585
|
-
'--skip-cross-check[Skip second-machine verification]'
|
|
2619
|
+
'--skip-cross-check[Skip second-machine verification]' \\
|
|
2620
|
+
'--verbose[Show step-by-step auth diagnostics]'
|
|
2586
2621
|
;;
|
|
2587
2622
|
create)
|
|
2588
2623
|
_arguments \\
|
|
@@ -2749,7 +2784,7 @@ var BASH_SCRIPT = `_computer() {
|
|
|
2749
2784
|
COMPREPLY=($(compgen -W "--json" -- "$cur"))
|
|
2750
2785
|
;;
|
|
2751
2786
|
claude-auth|claude-login)
|
|
2752
|
-
COMPREPLY=($(compgen -W "--machine --keep-helper --skip-cross-check" -- "$cur"))
|
|
2787
|
+
COMPREPLY=($(compgen -W "--machine --keep-helper --skip-cross-check --verbose" -- "$cur"))
|
|
2753
2788
|
;;
|
|
2754
2789
|
create)
|
|
2755
2790
|
COMPREPLY=($(compgen -W "--name --tier --interactive --runtime-family --source-kind --image-family --image-ref --use-platform-default --primary-port --primary-path --healthcheck-type --healthcheck-value --ssh-enabled --ssh-disabled --vnc-enabled --vnc-disabled" -- "$cur"))
|