mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-04 08:28:19 +08:00
* feat(sandbox): expose services during creation Signed-off-by: Drew Newberry <anewberry@nvidia.com> * feat(providers): refresh Codex credentials in gateway Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(cli): normalize create-time service URLs Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(server): roll back failed service exposure Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs(example): simplify Codex provider setup Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs(example): separate provider setup commands Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(sandbox): harden create-time service exposure Signed-off-by: Drew Newberry <anewberry@nvidia.com> * docs(example): bundle Codex provider profile Signed-off-by: Drew Newberry <anewberry@nvidia.com> * fix(example): allow npm-installed Codex binary Signed-off-by: Drew Newberry <anewberry@nvidia.com> --------- Signed-off-by: Drew Newberry <anewberry@nvidia.com>
70 lines
2.0 KiB
JavaScript
70 lines
2.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const { spawn } = require("child_process");
|
|
|
|
const required = [
|
|
"CODEX_AUTH_ACCESS_TOKEN",
|
|
"CODEX_AUTH_ACCOUNT_ID",
|
|
];
|
|
for (const name of required) {
|
|
if (!process.env[name]) {
|
|
throw new Error(`missing required provider credential: ${name}`);
|
|
}
|
|
}
|
|
|
|
const b64u = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
|
|
const now = Math.floor(Date.now() / 1000);
|
|
const idToken = [
|
|
b64u({ alg: "none", typ: "JWT" }),
|
|
b64u({
|
|
iss: "https://auth.openai.com",
|
|
aud: "codex",
|
|
sub: "openshell-app-server",
|
|
email: "app-server@openshell.local",
|
|
iat: now,
|
|
exp: now + 3600,
|
|
}),
|
|
"placeholder",
|
|
].join(".");
|
|
|
|
const codexHome = path.join(process.env.HOME, ".codex");
|
|
fs.mkdirSync(codexHome, { recursive: true });
|
|
fs.writeFileSync(path.join(codexHome, "auth.json"), JSON.stringify({
|
|
// The gateway owns token refresh; Codex must not attempt to refresh these
|
|
// externally managed tokens itself.
|
|
auth_mode: "chatgptAuthTokens",
|
|
OPENAI_API_KEY: null,
|
|
tokens: {
|
|
// Provider values are opaque stable handles. Codex parses the ID token
|
|
// locally, so use a short-lived, non-secret identity placeholder for it.
|
|
id_token: idToken,
|
|
access_token: process.env.CODEX_AUTH_ACCESS_TOKEN,
|
|
refresh_token: "",
|
|
account_id: process.env.CODEX_AUTH_ACCOUNT_ID,
|
|
},
|
|
last_refresh: new Date().toISOString(),
|
|
}, null, 2), { mode: 0o600 });
|
|
|
|
const port = process.env.CODEX_APP_SERVER_PORT || "4500";
|
|
const server = spawn(
|
|
"codex",
|
|
["app-server", "--listen", `ws://127.0.0.1:${port}`],
|
|
{ stdio: "inherit" },
|
|
);
|
|
server.on("error", (error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|
|
server.on("exit", (code, signal) => {
|
|
if (signal) {
|
|
process.kill(process.pid, signal);
|
|
} else {
|
|
process.exit(code ?? 1);
|
|
}
|
|
});
|