@playdrop/playdrop-cli 0.12.18 → 0.12.20
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/config/client-meta.json +1 -1
- package/dist/commands/worker/runtime.d.ts +1 -0
- package/dist/commands/worker/runtime.js +11 -0
- package/dist/commands/worker.d.ts +1 -3
- package/dist/commands/worker.js +22 -68
- package/node_modules/@playdrop/config/client-meta.json +1 -1
- package/package.json +1 -1
package/config/client-meta.json
CHANGED
|
@@ -712,6 +712,17 @@ function buildWorkerChildEnv(input) {
|
|
|
712
712
|
}
|
|
713
713
|
child.CLAUDE_CONFIG_DIR = claudeConfigDir;
|
|
714
714
|
}
|
|
715
|
+
// Claude sessions inherit the host's real HOME and Claude config on purpose: the machine is
|
|
716
|
+
// logged in with the Claude CLI and we call it exactly as a human does. The worker never
|
|
717
|
+
// stages, copies, or refreshes Claude credentials. The agent's `playdrop` CLI is still scoped
|
|
718
|
+
// to a task session through PLAYDROP_CONFIG_PATH rather than by hijacking HOME.
|
|
719
|
+
if (input.playdropConfigPath !== undefined) {
|
|
720
|
+
const playdropConfigPath = input.playdropConfigPath.trim();
|
|
721
|
+
if (!playdropConfigPath || !node_path_1.default.isAbsolute(playdropConfigPath)) {
|
|
722
|
+
throw new Error('invalid_worker_child_playdrop_config_path');
|
|
723
|
+
}
|
|
724
|
+
child.PLAYDROP_CONFIG_PATH = playdropConfigPath;
|
|
725
|
+
}
|
|
715
726
|
if (input.playwrightBrowsersPath !== undefined) {
|
|
716
727
|
const playwrightBrowsersPath = input.playwrightBrowsersPath.trim();
|
|
717
728
|
if (!playwrightBrowsersPath || !node_path_1.default.isAbsolute(playwrightBrowsersPath)) {
|
|
@@ -249,11 +249,9 @@ export declare function prepareClaudeRunConfig(input: {
|
|
|
249
249
|
workspaceDir: string;
|
|
250
250
|
workerUsername: string;
|
|
251
251
|
envName: string;
|
|
252
|
-
sourceCredentialsPath?: string;
|
|
253
252
|
playdropConfig?: ReturnType<typeof loadConfig>;
|
|
254
253
|
}): Promise<{
|
|
255
|
-
|
|
256
|
-
claudeConfigDir: string;
|
|
254
|
+
playdropConfigPath: string;
|
|
257
255
|
}>;
|
|
258
256
|
export declare function removeAgentRunCredentials(workspaceDir: string): Promise<void>;
|
|
259
257
|
export declare function removeStaleAgentRunCredentials(workerHomeDir?: string): Promise<void>;
|
package/dist/commands/worker.js
CHANGED
|
@@ -1958,78 +1958,32 @@ async function stageWorkerPlaydropSession(input) {
|
|
|
1958
1958
|
},
|
|
1959
1959
|
}, null, 2), { mode: 0o600 });
|
|
1960
1960
|
await (0, promises_1.chmod)(playdropConfigPath, 0o600);
|
|
1961
|
+
return playdropConfigPath;
|
|
1961
1962
|
}
|
|
1962
1963
|
async function prepareClaudeRunConfig(input) {
|
|
1963
1964
|
const runRoot = node_path_1.default.join(input.workspaceDir, '.playdrop', 'claude-run');
|
|
1964
1965
|
const homeDir = node_path_1.default.join(runRoot, 'home');
|
|
1965
|
-
const claudeConfigDir = node_path_1.default.join(runRoot, 'config');
|
|
1966
1966
|
await (0, promises_1.rm)(runRoot, { recursive: true, force: true });
|
|
1967
1967
|
await (0, promises_1.mkdir)(runRoot, { recursive: true, mode: 0o700 });
|
|
1968
1968
|
await (0, promises_1.chmod)(runRoot, 0o700);
|
|
1969
1969
|
await (0, promises_1.mkdir)(homeDir, { mode: 0o700 });
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
const result = await execFileAsync('security', [
|
|
1988
|
-
'find-generic-password',
|
|
1989
|
-
'-s',
|
|
1990
|
-
'Claude Code-credentials',
|
|
1991
|
-
'-w',
|
|
1992
|
-
], { maxBuffer: 1024 * 1024 });
|
|
1993
|
-
rawCredentials = result.stdout;
|
|
1994
|
-
}
|
|
1995
|
-
catch {
|
|
1996
|
-
throw new Error('worker_claude_credentials_missing:macos_keychain');
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
else {
|
|
2000
|
-
throw new Error(`worker_claude_credentials_missing:${defaultCredentialsPath}`);
|
|
2001
|
-
}
|
|
2002
|
-
let credentials;
|
|
2003
|
-
try {
|
|
2004
|
-
credentials = JSON.parse(rawCredentials);
|
|
2005
|
-
}
|
|
2006
|
-
catch {
|
|
2007
|
-
throw new Error('worker_claude_credentials_invalid_json');
|
|
2008
|
-
}
|
|
2009
|
-
const credentialObject = typeof credentials === 'object' && credentials !== null && !Array.isArray(credentials)
|
|
2010
|
-
? credentials
|
|
2011
|
-
: null;
|
|
2012
|
-
const oauthValue = credentialObject?.claudeAiOauth;
|
|
2013
|
-
const claudeAiOauth = typeof oauthValue === 'object' && oauthValue !== null && !Array.isArray(oauthValue)
|
|
2014
|
-
? oauthValue
|
|
2015
|
-
: null;
|
|
2016
|
-
if (!claudeAiOauth
|
|
2017
|
-
|| typeof claudeAiOauth.accessToken !== 'string'
|
|
2018
|
-
|| !claudeAiOauth.accessToken.trim()
|
|
2019
|
-
|| typeof claudeAiOauth.refreshToken !== 'string'
|
|
2020
|
-
|| !claudeAiOauth.refreshToken.trim()) {
|
|
2021
|
-
throw new Error('worker_claude_oauth_credentials_missing');
|
|
2022
|
-
}
|
|
2023
|
-
const stagedCredentialsPath = node_path_1.default.join(claudeConfigDir, '.credentials.json');
|
|
2024
|
-
await (0, promises_1.writeFile)(stagedCredentialsPath, `${JSON.stringify({ claudeAiOauth })}\n`, { mode: 0o600 });
|
|
2025
|
-
await (0, promises_1.chmod)(stagedCredentialsPath, 0o600);
|
|
2026
|
-
await stageWorkerPlaydropSession({
|
|
2027
|
-
homeDir,
|
|
2028
|
-
workerUsername: input.workerUsername,
|
|
2029
|
-
envName: input.envName,
|
|
2030
|
-
playdropConfig: input.playdropConfig,
|
|
2031
|
-
});
|
|
2032
|
-
return { homeDir, claudeConfigDir };
|
|
1970
|
+
// The worker does NOT manage Claude authentication. The host is logged in with the Claude CLI;
|
|
1971
|
+
// we call `claude` and let it use the machine's own login exactly as a human would.
|
|
1972
|
+
//
|
|
1973
|
+
// We used to copy the OAuth credential into this per-task config dir. That is what logged the
|
|
1974
|
+
// machine out: the copy refreshed on first use after the 8h access-token expiry, Anthropic
|
|
1975
|
+
// rotated the refresh token (invalidating the one still in the keychain), and the refreshed
|
|
1976
|
+
// credential was thrown away with the task workspace. The host was then permanently logged out.
|
|
1977
|
+
// Observed twice in production (2026-07-13 19:50, 2026-07-14 13:00:23, the latter three seconds
|
|
1978
|
+
// after task 449's Claude exited). Never stage, copy, or write Claude credentials here.
|
|
1979
|
+
return {
|
|
1980
|
+
playdropConfigPath: await stageWorkerPlaydropSession({
|
|
1981
|
+
homeDir,
|
|
1982
|
+
workerUsername: input.workerUsername,
|
|
1983
|
+
envName: input.envName,
|
|
1984
|
+
playdropConfig: input.playdropConfig,
|
|
1985
|
+
}),
|
|
1986
|
+
};
|
|
2033
1987
|
}
|
|
2034
1988
|
async function removeAgentRunCredentials(workspaceDir) {
|
|
2035
1989
|
await Promise.all([
|
|
@@ -2124,7 +2078,7 @@ async function runCodex(input) {
|
|
|
2124
2078
|
};
|
|
2125
2079
|
}
|
|
2126
2080
|
async function runClaude(input) {
|
|
2127
|
-
const {
|
|
2081
|
+
const { playdropConfigPath } = await prepareClaudeRunConfig({
|
|
2128
2082
|
workspaceDir: input.workspaceDir,
|
|
2129
2083
|
workerUsername: input.workerUsername,
|
|
2130
2084
|
envName: input.envName,
|
|
@@ -2135,7 +2089,8 @@ async function runClaude(input) {
|
|
|
2135
2089
|
: null;
|
|
2136
2090
|
let playwrightMcpConfigPath = null;
|
|
2137
2091
|
if (input.enablePlaywrightMcp) {
|
|
2138
|
-
playwrightMcpConfigPath = node_path_1.default.join(
|
|
2092
|
+
playwrightMcpConfigPath = node_path_1.default.join(input.workspaceDir, '.playdrop', 'claude-run', 'playwright-mcp.json');
|
|
2093
|
+
(0, node_fs_1.mkdirSync)(node_path_1.default.dirname(playwrightMcpConfigPath), { recursive: true });
|
|
2139
2094
|
(0, node_fs_1.writeFileSync)(playwrightMcpConfigPath, `${JSON.stringify((0, runtime_1.buildPlaywrightMcpServerConfig)(), null, 2)}\n`, 'utf8');
|
|
2140
2095
|
}
|
|
2141
2096
|
const result = await (0, runtime_1.runLoggedProcess)({
|
|
@@ -2157,8 +2112,7 @@ async function runClaude(input) {
|
|
|
2157
2112
|
envName: input.envName,
|
|
2158
2113
|
eventDir: input.eventDir,
|
|
2159
2114
|
devPort: input.devPort,
|
|
2160
|
-
|
|
2161
|
-
claudeConfigDir,
|
|
2115
|
+
playdropConfigPath,
|
|
2162
2116
|
playwrightBrowsersPath: resolveWorkerPlaywrightBrowsersPath(),
|
|
2163
2117
|
}),
|
|
2164
2118
|
stdin: input.prompt,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playdrop/playdrop-cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.20",
|
|
4
4
|
"description": "Official Playdrop CLI for publishing browser games, creator apps, and AI-generated game assets on playdrop.ai",
|
|
5
5
|
"homepage": "https://www.playdrop.ai",
|
|
6
6
|
"repository": {
|