amai 0.0.17 → 0.0.18

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/cli.cjs CHANGED
@@ -5,7 +5,7 @@ var pc5 = require('picocolors');
5
5
  var WebSocket = require('ws');
6
6
  var zod = require('zod');
7
7
  var path10 = require('path');
8
- var fs9 = require('fs');
8
+ var fs10 = require('fs');
9
9
  var os3 = require('os');
10
10
  var fs8 = require('fs/promises');
11
11
  var hono = require('hono');
@@ -22,7 +22,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
22
22
  var pc5__default = /*#__PURE__*/_interopDefault(pc5);
23
23
  var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
24
24
  var path10__default = /*#__PURE__*/_interopDefault(path10);
25
- var fs9__default = /*#__PURE__*/_interopDefault(fs9);
25
+ var fs10__default = /*#__PURE__*/_interopDefault(fs10);
26
26
  var os3__default = /*#__PURE__*/_interopDefault(os3);
27
27
  var fs8__default = /*#__PURE__*/_interopDefault(fs8);
28
28
  var readline__default = /*#__PURE__*/_interopDefault(readline);
@@ -52,11 +52,11 @@ function isPathWithinProject(filePath, projectCwd) {
52
52
  }
53
53
  function safeRealpath(p) {
54
54
  try {
55
- return fs9__default.default.realpathSync(p);
55
+ return fs10__default.default.realpathSync(p);
56
56
  } catch {
57
57
  const parent = path10__default.default.dirname(p);
58
58
  try {
59
- const realParent = fs9__default.default.realpathSync(parent);
59
+ const realParent = fs10__default.default.realpathSync(parent);
60
60
  return path10__default.default.join(realParent, path10__default.default.basename(p));
61
61
  } catch {
62
62
  return path10__default.default.resolve(p);
@@ -353,16 +353,16 @@ var Diff = class {
353
353
  }
354
354
  }
355
355
  }
356
- addToPath(path16, added, removed, oldPosInc, options) {
357
- const last = path16.lastComponent;
356
+ addToPath(path17, added, removed, oldPosInc, options) {
357
+ const last = path17.lastComponent;
358
358
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
359
359
  return {
360
- oldPos: path16.oldPos + oldPosInc,
360
+ oldPos: path17.oldPos + oldPosInc,
361
361
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
362
362
  };
363
363
  } else {
364
364
  return {
365
- oldPos: path16.oldPos + oldPosInc,
365
+ oldPos: path17.oldPos + oldPosInc,
366
366
  lastComponent: { count: 1, added, removed, previousComponent: last }
367
367
  };
368
368
  }
@@ -518,7 +518,7 @@ function calculateDiffStats(oldContent, newContent) {
518
518
  return { linesAdded, linesRemoved };
519
519
  }
520
520
 
521
- // src/tools/apply-patch.ts
521
+ // src/tools/stringReplace.ts
522
522
  zod.z.object({
523
523
  file_path: zod.z.string().describe("The path to the file you want to search and replace in. You can use either a relative path in the workspace or an absolute path. If an absolute path is provided, it will be preserved as is"),
524
524
  new_string: zod.z.string().describe("The edited text to replace the old_string (must be different from the old_string)"),
@@ -628,8 +628,8 @@ var apply_patch = async function(input, projectCwd) {
628
628
  };
629
629
  }
630
630
  };
631
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
632
- var CLIENT_ID = "client_01K4Y8A67H544Z6J8A47E5GJ9A";
631
+ var DEFAULT_SERVER_URL = "ws://localhost:3000";
632
+ var CLIENT_ID = "client_01K4Y8A5Q3FYGXD362BJQ6AGYD";
633
633
  var AMA_DIR = path10__default.default.join(os3__default.default.homedir(), ".amai");
634
634
  var CODE_DIR = path10__default.default.join(AMA_DIR, "code");
635
635
  var STORAGE_DIR = path10__default.default.join(AMA_DIR, "storage");
@@ -804,7 +804,7 @@ async function getRipgrepPath() {
804
804
  "/usr/bin/rg"
805
805
  ];
806
806
  for (const rgPath of paths) {
807
- if (fs9__default.default.existsSync(rgPath)) {
807
+ if (fs10__default.default.existsSync(rgPath)) {
808
808
  _cachedRgPath = rgPath;
809
809
  return rgPath;
810
810
  }
@@ -824,7 +824,7 @@ async function getMtimesBatched(files) {
824
824
  return { path: filePath, mtime };
825
825
  })
826
826
  );
827
- results.forEach(({ path: path16, mtime }) => mtimeMap.set(path16, mtime));
827
+ results.forEach(({ path: path17, mtime }) => mtimeMap.set(path17, mtime));
828
828
  }
829
829
  return mtimeMap;
830
830
  }
@@ -853,7 +853,7 @@ var grepTool = async function(input, projectCwd) {
853
853
  }
854
854
  }
855
855
  }
856
- if (!fs9__default.default.existsSync(searchDir)) {
856
+ if (!fs10__default.default.existsSync(searchDir)) {
857
857
  return {
858
858
  success: false,
859
859
  message: `Directory not found: ${searchDir}`,
@@ -1036,7 +1036,7 @@ var globTool = async function(input, projectCwd) {
1036
1036
  try {
1037
1037
  const basePath = projectCwd || process.cwd();
1038
1038
  const searchPath = inputPath ? resolveProjectPath(inputPath, basePath) : basePath;
1039
- if (!fs9__default.default.existsSync(searchPath)) {
1039
+ if (!fs10__default.default.existsSync(searchPath)) {
1040
1040
  return {
1041
1041
  success: false,
1042
1042
  message: `Directory not found: ${searchPath}`,
@@ -1240,14 +1240,14 @@ var list = async function(input, projectCwd) {
1240
1240
  };
1241
1241
  }
1242
1242
  }
1243
- if (!fs9__default.default.existsSync(absolutePath)) {
1243
+ if (!fs10__default.default.existsSync(absolutePath)) {
1244
1244
  return {
1245
1245
  success: false,
1246
1246
  message: `Directory not found: ${absolutePath}`,
1247
1247
  error: "DIR_NOT_FOUND"
1248
1248
  };
1249
1249
  }
1250
- const stats = fs9__default.default.statSync(absolutePath);
1250
+ const stats = fs10__default.default.statSync(absolutePath);
1251
1251
  if (!stats.isDirectory()) {
1252
1252
  return {
1253
1253
  success: false,
@@ -1264,7 +1264,7 @@ var list = async function(input, projectCwd) {
1264
1264
  }
1265
1265
  let entries;
1266
1266
  try {
1267
- entries = fs9__default.default.readdirSync(currentDir, { withFileTypes: true });
1267
+ entries = fs10__default.default.readdirSync(currentDir, { withFileTypes: true });
1268
1268
  } catch {
1269
1269
  return;
1270
1270
  }
@@ -1379,10 +1379,10 @@ var CREDENTIALS_DIR = path10__default.default.join(os3__default.default.homedir(
1379
1379
  var CREDENTIALS_PATH = path10__default.default.join(CREDENTIALS_DIR, "credentials.json");
1380
1380
  function isAuthenticated() {
1381
1381
  try {
1382
- if (!fs9__default.default.existsSync(CREDENTIALS_PATH)) {
1382
+ if (!fs10__default.default.existsSync(CREDENTIALS_PATH)) {
1383
1383
  return false;
1384
1384
  }
1385
- const raw = fs9__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1385
+ const raw = fs10__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1386
1386
  const data = JSON.parse(raw);
1387
1387
  return Boolean(data && data.access_token);
1388
1388
  } catch {
@@ -1391,10 +1391,10 @@ function isAuthenticated() {
1391
1391
  }
1392
1392
  function saveTokens(tokens) {
1393
1393
  try {
1394
- if (!fs9__default.default.existsSync(CREDENTIALS_DIR)) {
1395
- fs9__default.default.mkdirSync(CREDENTIALS_DIR, { recursive: true });
1394
+ if (!fs10__default.default.existsSync(CREDENTIALS_DIR)) {
1395
+ fs10__default.default.mkdirSync(CREDENTIALS_DIR, { recursive: true });
1396
1396
  }
1397
- fs9__default.default.writeFileSync(
1397
+ fs10__default.default.writeFileSync(
1398
1398
  CREDENTIALS_PATH,
1399
1399
  JSON.stringify(tokens, null, 2),
1400
1400
  "utf8"
@@ -1405,18 +1405,18 @@ function saveTokens(tokens) {
1405
1405
  }
1406
1406
  function logout() {
1407
1407
  try {
1408
- if (fs9__default.default.existsSync(CREDENTIALS_PATH)) {
1409
- fs9__default.default.unlinkSync(CREDENTIALS_PATH);
1408
+ if (fs10__default.default.existsSync(CREDENTIALS_PATH)) {
1409
+ fs10__default.default.unlinkSync(CREDENTIALS_PATH);
1410
1410
  }
1411
1411
  } catch (error) {
1412
1412
  console.error(pc5__default.default.red("Failed to logout"), error);
1413
1413
  }
1414
1414
  }
1415
1415
  function getTokens() {
1416
- if (!fs9__default.default.existsSync(CREDENTIALS_PATH)) {
1416
+ if (!fs10__default.default.existsSync(CREDENTIALS_PATH)) {
1417
1417
  return null;
1418
1418
  }
1419
- const raw = fs9__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1419
+ const raw = fs10__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1420
1420
  const data = JSON.parse(raw);
1421
1421
  return data;
1422
1422
  }
@@ -1515,10 +1515,10 @@ async function login() {
1515
1515
  }
1516
1516
  var getUserId = () => {
1517
1517
  try {
1518
- if (!fs9__default.default.existsSync(CREDENTIALS_PATH)) {
1518
+ if (!fs10__default.default.existsSync(CREDENTIALS_PATH)) {
1519
1519
  return;
1520
1520
  }
1521
- const raw = fs9__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1521
+ const raw = fs10__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1522
1522
  const data = JSON.parse(raw);
1523
1523
  const fromUserObject = data.user?.id;
1524
1524
  const fromTopLevel = data.sub ?? data.user_id;
@@ -1706,14 +1706,14 @@ var ProjectRegistry = class {
1706
1706
  }
1707
1707
  load() {
1708
1708
  try {
1709
- if (fs9__default.default.existsSync(REGISTRY_FILE)) {
1710
- const data = fs9__default.default.readFileSync(REGISTRY_FILE, "utf8");
1709
+ if (fs10__default.default.existsSync(REGISTRY_FILE)) {
1710
+ const data = fs10__default.default.readFileSync(REGISTRY_FILE, "utf8");
1711
1711
  const parsed = JSON.parse(data);
1712
1712
  if (!Array.isArray(parsed)) {
1713
1713
  console.error("Invalid project registry format: expected array, got", typeof parsed);
1714
1714
  const backupFile = REGISTRY_FILE + ".backup." + Date.now();
1715
- fs9__default.default.copyFileSync(REGISTRY_FILE, backupFile);
1716
- fs9__default.default.unlinkSync(REGISTRY_FILE);
1715
+ fs10__default.default.copyFileSync(REGISTRY_FILE, backupFile);
1716
+ fs10__default.default.unlinkSync(REGISTRY_FILE);
1717
1717
  return;
1718
1718
  }
1719
1719
  const projects = parsed;
@@ -1726,11 +1726,11 @@ var ProjectRegistry = class {
1726
1726
  }
1727
1727
  } catch (error) {
1728
1728
  console.error("Failed to load project registry:", error);
1729
- if (fs9__default.default.existsSync(REGISTRY_FILE)) {
1729
+ if (fs10__default.default.existsSync(REGISTRY_FILE)) {
1730
1730
  try {
1731
1731
  const backupFile = REGISTRY_FILE + ".backup." + Date.now();
1732
- fs9__default.default.copyFileSync(REGISTRY_FILE, backupFile);
1733
- fs9__default.default.unlinkSync(REGISTRY_FILE);
1732
+ fs10__default.default.copyFileSync(REGISTRY_FILE, backupFile);
1733
+ fs10__default.default.unlinkSync(REGISTRY_FILE);
1734
1734
  console.log("Corrupted registry file backed up and removed. Starting fresh.");
1735
1735
  } catch (backupError) {
1736
1736
  }
@@ -1739,11 +1739,11 @@ var ProjectRegistry = class {
1739
1739
  }
1740
1740
  save() {
1741
1741
  try {
1742
- if (!fs9__default.default.existsSync(AMA_DIR)) {
1743
- fs9__default.default.mkdirSync(AMA_DIR, { recursive: true });
1742
+ if (!fs10__default.default.existsSync(AMA_DIR)) {
1743
+ fs10__default.default.mkdirSync(AMA_DIR, { recursive: true });
1744
1744
  }
1745
1745
  const projects = Array.from(this.projects.values());
1746
- fs9__default.default.writeFileSync(REGISTRY_FILE, JSON.stringify(projects, null, 2), "utf8");
1746
+ fs10__default.default.writeFileSync(REGISTRY_FILE, JSON.stringify(projects, null, 2), "utf8");
1747
1747
  } catch (error) {
1748
1748
  console.error("Failed to save project registry:", error);
1749
1749
  }
@@ -1783,7 +1783,7 @@ var ProjectRegistry = class {
1783
1783
  var projectRegistry = new ProjectRegistry();
1784
1784
  var ignoreFiles = ["node_modules", ".git", ".next", ".env", ".env.local", ".env.development.local", ".env.test.local", ".env.production.local", ".output", ".turbo", ".vercel", ".next", ".tanstack", ".nitro", ".wrangler", ".alchemy", ".coverage", ".nyc_output", ".cache", "tmp", "temp", ".idea", ".vscode", ".zig-cache", "zig-out", ".coverage", "coverage", "logs", ".venv", "venv", "env", ".next", ".turbo", ".vercel", ".output", ".tanstack", ".nitro", ".wrangler", ".alchemy", ".coverage", ".nyc_output", ".cache", "tmp", "temp", ".idea", ".vscode", ".zig-cache", "zig-out", ".coverage", "coverage", "logs", ".venv", "venv", "env"];
1785
1785
  var getContext = (dir, base = dir, allFiles = []) => {
1786
- const filePath = fs9.readdirSync(dir, { withFileTypes: true });
1786
+ const filePath = fs10.readdirSync(dir, { withFileTypes: true });
1787
1787
  for (const file of filePath) {
1788
1788
  if (ignoreFiles.includes(file.name)) continue;
1789
1789
  const fullPath = path10__default.default.join(dir, file.name);
@@ -1812,7 +1812,7 @@ function getWorkspaceStoragePath(ide) {
1812
1812
  } else {
1813
1813
  const capitalizedPath = path10__default.default.join(HOME, ".config", appName, "User", "workspaceStorage");
1814
1814
  const lowercasePath = path10__default.default.join(HOME, ".config", appNameLower, "User", "workspaceStorage");
1815
- if (fs9__default.default.existsSync(capitalizedPath)) {
1815
+ if (fs10__default.default.existsSync(capitalizedPath)) {
1816
1816
  return capitalizedPath;
1817
1817
  }
1818
1818
  return lowercasePath;
@@ -1821,16 +1821,16 @@ function getWorkspaceStoragePath(ide) {
1821
1821
  function scanWorkspaceStorage(ide) {
1822
1822
  const projects = [];
1823
1823
  const storagePath = getWorkspaceStoragePath(ide);
1824
- if (!fs9__default.default.existsSync(storagePath)) {
1824
+ if (!fs10__default.default.existsSync(storagePath)) {
1825
1825
  return projects;
1826
1826
  }
1827
1827
  try {
1828
- const workspaces = fs9__default.default.readdirSync(storagePath);
1828
+ const workspaces = fs10__default.default.readdirSync(storagePath);
1829
1829
  for (const workspace of workspaces) {
1830
1830
  const workspaceJsonPath = path10__default.default.join(storagePath, workspace, "workspace.json");
1831
- if (fs9__default.default.existsSync(workspaceJsonPath)) {
1831
+ if (fs10__default.default.existsSync(workspaceJsonPath)) {
1832
1832
  try {
1833
- const content = fs9__default.default.readFileSync(workspaceJsonPath, "utf-8");
1833
+ const content = fs10__default.default.readFileSync(workspaceJsonPath, "utf-8");
1834
1834
  const data = JSON.parse(content);
1835
1835
  if (data.folder && typeof data.folder === "string") {
1836
1836
  let projectPath = data.folder;
@@ -1838,7 +1838,7 @@ function scanWorkspaceStorage(ide) {
1838
1838
  projectPath = projectPath.replace("file://", "");
1839
1839
  projectPath = decodeURIComponent(projectPath);
1840
1840
  }
1841
- if (fs9__default.default.existsSync(projectPath) && fs9__default.default.statSync(projectPath).isDirectory()) {
1841
+ if (fs10__default.default.existsSync(projectPath) && fs10__default.default.statSync(projectPath).isDirectory()) {
1842
1842
  projects.push({
1843
1843
  name: path10__default.default.basename(projectPath),
1844
1844
  path: projectPath,
@@ -1862,11 +1862,11 @@ var scanIdeProjects = async () => {
1862
1862
  const seenPaths = /* @__PURE__ */ new Set();
1863
1863
  const addProject = (projectPath, ide) => {
1864
1864
  try {
1865
- const resolvedPath = fs9__default.default.realpathSync(projectPath);
1866
- if (fs9__default.default.existsSync(resolvedPath) && fs9__default.default.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
1865
+ const resolvedPath = fs10__default.default.realpathSync(projectPath);
1866
+ if (fs10__default.default.existsSync(resolvedPath) && fs10__default.default.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
1867
1867
  const isIdeProjectsDir = Object.values(IDE_PROJECTS_PATHS).some((ideDir) => {
1868
1868
  try {
1869
- return fs9__default.default.realpathSync(ideDir) === resolvedPath;
1869
+ return fs10__default.default.realpathSync(ideDir) === resolvedPath;
1870
1870
  } catch {
1871
1871
  return false;
1872
1872
  }
@@ -1893,30 +1893,30 @@ var scanIdeProjects = async () => {
1893
1893
  }
1894
1894
  for (const [ide, dirPath] of Object.entries(IDE_PROJECTS_PATHS)) {
1895
1895
  if (ide === "cursor" || ide === "vscode") continue;
1896
- if (fs9__default.default.existsSync(dirPath)) {
1897
- const projects = fs9__default.default.readdirSync(dirPath);
1896
+ if (fs10__default.default.existsSync(dirPath)) {
1897
+ const projects = fs10__default.default.readdirSync(dirPath);
1898
1898
  projects.forEach((project) => {
1899
1899
  const projectPath = path10__default.default.join(dirPath, project);
1900
1900
  try {
1901
- const stats = fs9__default.default.lstatSync(projectPath);
1901
+ const stats = fs10__default.default.lstatSync(projectPath);
1902
1902
  let actualPath = null;
1903
1903
  if (stats.isSymbolicLink()) {
1904
- actualPath = fs9__default.default.realpathSync(projectPath);
1904
+ actualPath = fs10__default.default.realpathSync(projectPath);
1905
1905
  } else if (stats.isFile()) {
1906
1906
  try {
1907
- let content = fs9__default.default.readFileSync(projectPath, "utf-8").trim();
1907
+ let content = fs10__default.default.readFileSync(projectPath, "utf-8").trim();
1908
1908
  if (content.startsWith("~/") || content === "~") {
1909
1909
  content = content.replace(/^~/, HOME);
1910
1910
  }
1911
1911
  const resolvedContent = path10__default.default.isAbsolute(content) ? content : path10__default.default.resolve(path10__default.default.dirname(projectPath), content);
1912
- if (fs9__default.default.existsSync(resolvedContent) && fs9__default.default.statSync(resolvedContent).isDirectory()) {
1913
- actualPath = fs9__default.default.realpathSync(resolvedContent);
1912
+ if (fs10__default.default.existsSync(resolvedContent) && fs10__default.default.statSync(resolvedContent).isDirectory()) {
1913
+ actualPath = fs10__default.default.realpathSync(resolvedContent);
1914
1914
  }
1915
1915
  } catch {
1916
1916
  return;
1917
1917
  }
1918
1918
  } else if (stats.isDirectory()) {
1919
- actualPath = fs9__default.default.realpathSync(projectPath);
1919
+ actualPath = fs10__default.default.realpathSync(projectPath);
1920
1920
  }
1921
1921
  if (actualPath) {
1922
1922
  addProject(actualPath, ide);
@@ -2181,6 +2181,396 @@ var Snapshot;
2181
2181
  return path10__default.default.join(Global.Path.data, "snapshot", projectId);
2182
2182
  }
2183
2183
  })(Snapshot || (Snapshot = {}));
2184
+ var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
2185
+ var ISSUER = "https://auth.openai.com";
2186
+ var OAUTH_PORT = 1455;
2187
+ var CREDENTIALS_PATH2 = path10__default.default.join(AMA_DIR, "codex-credentials.json");
2188
+ var CALLBACK_PATH = "/auth/callback";
2189
+ var OAUTH_TIMEOUT_MS = 5 * 60 * 1e3;
2190
+ var REFRESH_BUFFER_MS = 60 * 1e3;
2191
+ var oauthServer;
2192
+ var pendingOAuth;
2193
+ var HTML_SUCCESS = `<!doctype html>
2194
+ <html>
2195
+ <head>
2196
+ <title>amai - Codex Authorization Successful</title>
2197
+ <style>
2198
+ body {
2199
+ font-family:
2200
+ system-ui,
2201
+ -apple-system,
2202
+ sans-serif;
2203
+ display: flex;
2204
+ justify-content: center;
2205
+ align-items: center;
2206
+ height: 100vh;
2207
+ margin: 0;
2208
+ background: #131010;
2209
+ color: #f1ecec;
2210
+ }
2211
+ .container {
2212
+ text-align: center;
2213
+ padding: 2rem;
2214
+ }
2215
+ h1 {
2216
+ color: #f1ecec;
2217
+ margin-bottom: 1rem;
2218
+ }
2219
+ p {
2220
+ color: #b7b1b1;
2221
+ }
2222
+ </style>
2223
+ </head>
2224
+ <body>
2225
+ <div class="container">
2226
+ <h1>Authorization Successful</h1>
2227
+ <p>You can close this window and return to ama.</p>
2228
+ </div>
2229
+ <script>
2230
+ setTimeout(() => window.close(), 2000)
2231
+ </script>
2232
+ </body>
2233
+ </html>`;
2234
+ var HTML_ERROR = (error) => `<!doctype html>
2235
+ <html>
2236
+ <head>
2237
+ <title>amai - Codex Authorization Failed</title>
2238
+ <style>
2239
+ body {
2240
+ font-family:
2241
+ system-ui,
2242
+ -apple-system,
2243
+ sans-serif;
2244
+ display: flex;
2245
+ justify-content: center;
2246
+ align-items: center;
2247
+ height: 100vh;
2248
+ margin: 0;
2249
+ background: #131010;
2250
+ color: #f1ecec;
2251
+ }
2252
+ .container {
2253
+ text-align: center;
2254
+ padding: 2rem;
2255
+ }
2256
+ h1 {
2257
+ color: #fc533a;
2258
+ margin-bottom: 1rem;
2259
+ }
2260
+ p {
2261
+ color: #b7b1b1;
2262
+ }
2263
+ .error {
2264
+ color: #ff917b;
2265
+ font-family: monospace;
2266
+ margin-top: 1rem;
2267
+ padding: 1rem;
2268
+ background: #3c140d;
2269
+ border-radius: 0.5rem;
2270
+ }
2271
+ </style>
2272
+ </head>
2273
+ <body>
2274
+ <div class="container">
2275
+ <h1>Authorization Failed</h1>
2276
+ <p>An error occurred during authorization.</p>
2277
+ <div class="error">${error}</div>
2278
+ </div>
2279
+ </body>
2280
+ </html>`;
2281
+ function ensureCredentialsDir() {
2282
+ if (!fs10__default.default.existsSync(AMA_DIR)) {
2283
+ fs10__default.default.mkdirSync(AMA_DIR, { recursive: true });
2284
+ }
2285
+ }
2286
+ function saveCredentials(credentials) {
2287
+ ensureCredentialsDir();
2288
+ fs10__default.default.writeFileSync(CREDENTIALS_PATH2, JSON.stringify(credentials, null, 2), "utf8");
2289
+ }
2290
+ function readCredentials() {
2291
+ if (!fs10__default.default.existsSync(CREDENTIALS_PATH2)) {
2292
+ return null;
2293
+ }
2294
+ const raw = fs10__default.default.readFileSync(CREDENTIALS_PATH2, "utf8");
2295
+ const parsed = JSON.parse(raw);
2296
+ if (typeof parsed.accessToken !== "string" || typeof parsed.refreshToken !== "string" || typeof parsed.accountId !== "string" || typeof parsed.expiresAt !== "number") {
2297
+ return null;
2298
+ }
2299
+ return parsed;
2300
+ }
2301
+ function generateRandomString(length) {
2302
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
2303
+ const bytes = crypto.getRandomValues(new Uint8Array(length));
2304
+ return Array.from(bytes).map((b) => chars[b % chars.length]).join("");
2305
+ }
2306
+ function base64UrlEncode(buffer) {
2307
+ const bytes = new Uint8Array(buffer);
2308
+ const binary = String.fromCharCode(...bytes);
2309
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
2310
+ }
2311
+ async function generatePKCE() {
2312
+ const verifier = generateRandomString(43);
2313
+ const encoder = new TextEncoder();
2314
+ const data = encoder.encode(verifier);
2315
+ const hash = await crypto.subtle.digest("SHA-256", data);
2316
+ const challenge = base64UrlEncode(hash);
2317
+ return { verifier, challenge };
2318
+ }
2319
+ function generateState() {
2320
+ return base64UrlEncode(crypto.getRandomValues(new Uint8Array(32)).buffer);
2321
+ }
2322
+ function parseJwtClaims(token) {
2323
+ const parts = token.split(".");
2324
+ if (parts.length !== 3) {
2325
+ return void 0;
2326
+ }
2327
+ try {
2328
+ return JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
2329
+ } catch {
2330
+ return void 0;
2331
+ }
2332
+ }
2333
+ function extractAccountIdFromClaims(claims) {
2334
+ return claims.chatgpt_account_id || claims["https://api.openai.com/auth"]?.chatgpt_account_id || claims.organizations?.[0]?.id;
2335
+ }
2336
+ function extractAccountId(tokens) {
2337
+ if (tokens.id_token) {
2338
+ const claims = parseJwtClaims(tokens.id_token);
2339
+ const accountId = claims && extractAccountIdFromClaims(claims);
2340
+ if (accountId) {
2341
+ return accountId;
2342
+ }
2343
+ }
2344
+ const accessClaims = parseJwtClaims(tokens.access_token);
2345
+ return accessClaims ? extractAccountIdFromClaims(accessClaims) : void 0;
2346
+ }
2347
+ function buildAuthorizeUrl(redirectUri, pkce, state) {
2348
+ const params = new URLSearchParams({
2349
+ response_type: "code",
2350
+ client_id: CLIENT_ID2,
2351
+ redirect_uri: redirectUri,
2352
+ scope: "openid profile email offline_access",
2353
+ code_challenge: pkce.challenge,
2354
+ code_challenge_method: "S256",
2355
+ id_token_add_organizations: "true",
2356
+ codex_cli_simplified_flow: "true",
2357
+ state,
2358
+ originator: "ama"
2359
+ });
2360
+ return `${ISSUER}/oauth/authorize?${params.toString()}`;
2361
+ }
2362
+ async function exchangeCodeForTokens(code, redirectUri, pkce) {
2363
+ const response = await fetch(`${ISSUER}/oauth/token`, {
2364
+ method: "POST",
2365
+ headers: {
2366
+ "Content-Type": "application/x-www-form-urlencoded"
2367
+ },
2368
+ body: new URLSearchParams({
2369
+ grant_type: "authorization_code",
2370
+ code,
2371
+ redirect_uri: redirectUri,
2372
+ client_id: CLIENT_ID2,
2373
+ code_verifier: pkce.verifier
2374
+ }).toString()
2375
+ });
2376
+ if (!response.ok) {
2377
+ throw new Error(`Token exchange failed: ${response.status}`);
2378
+ }
2379
+ return response.json();
2380
+ }
2381
+ async function refreshAccessToken(refreshToken) {
2382
+ const response = await fetch(`${ISSUER}/oauth/token`, {
2383
+ method: "POST",
2384
+ headers: {
2385
+ "Content-Type": "application/x-www-form-urlencoded"
2386
+ },
2387
+ body: new URLSearchParams({
2388
+ grant_type: "refresh_token",
2389
+ refresh_token: refreshToken,
2390
+ client_id: CLIENT_ID2
2391
+ }).toString()
2392
+ });
2393
+ if (!response.ok) {
2394
+ throw new Error(`Token refresh failed: ${response.status}`);
2395
+ }
2396
+ return response.json();
2397
+ }
2398
+ async function startOAuthServer() {
2399
+ if (oauthServer) {
2400
+ return { redirectUri: `http://localhost:${OAUTH_PORT}${CALLBACK_PATH}` };
2401
+ }
2402
+ oauthServer = Bun.serve({
2403
+ port: OAUTH_PORT,
2404
+ fetch(request) {
2405
+ const url = new URL(request.url);
2406
+ if (url.pathname !== CALLBACK_PATH) {
2407
+ return new Response("Not found", { status: 404 });
2408
+ }
2409
+ const code = url.searchParams.get("code");
2410
+ const state = url.searchParams.get("state");
2411
+ const error = url.searchParams.get("error");
2412
+ const errorDescription = url.searchParams.get("error_description");
2413
+ if (error) {
2414
+ const message = errorDescription || error;
2415
+ pendingOAuth?.reject(new Error(message));
2416
+ pendingOAuth = void 0;
2417
+ return new Response(HTML_ERROR(message), {
2418
+ headers: { "Content-Type": "text/html" }
2419
+ });
2420
+ }
2421
+ if (!code) {
2422
+ const message = "Missing authorization code";
2423
+ pendingOAuth?.reject(new Error(message));
2424
+ pendingOAuth = void 0;
2425
+ return new Response(HTML_ERROR(message), {
2426
+ status: 400,
2427
+ headers: { "Content-Type": "text/html" }
2428
+ });
2429
+ }
2430
+ if (!pendingOAuth || state !== pendingOAuth.state) {
2431
+ const message = "Invalid state - potential CSRF attack";
2432
+ pendingOAuth?.reject(new Error(message));
2433
+ pendingOAuth = void 0;
2434
+ return new Response(HTML_ERROR(message), {
2435
+ status: 400,
2436
+ headers: { "Content-Type": "text/html" }
2437
+ });
2438
+ }
2439
+ const current = pendingOAuth;
2440
+ pendingOAuth = void 0;
2441
+ exchangeCodeForTokens(code, `http://localhost:${OAUTH_PORT}${CALLBACK_PATH}`, current.pkce).then((tokens) => current.resolve(tokens)).catch((err) => current.reject(err));
2442
+ return new Response(HTML_SUCCESS, {
2443
+ headers: { "Content-Type": "text/html" }
2444
+ });
2445
+ }
2446
+ });
2447
+ return { redirectUri: `http://localhost:${OAUTH_PORT}${CALLBACK_PATH}` };
2448
+ }
2449
+ function stopOAuthServer() {
2450
+ if (oauthServer) {
2451
+ oauthServer.stop();
2452
+ oauthServer = void 0;
2453
+ }
2454
+ }
2455
+ function waitForOAuthCallback(pkce, state) {
2456
+ if (pendingOAuth) {
2457
+ throw new Error("Codex authorization is already in progress");
2458
+ }
2459
+ return new Promise((resolve, reject) => {
2460
+ const timeout = setTimeout(() => {
2461
+ if (pendingOAuth) {
2462
+ pendingOAuth = void 0;
2463
+ reject(new Error("OAuth callback timeout - authorization took too long"));
2464
+ }
2465
+ }, OAUTH_TIMEOUT_MS);
2466
+ pendingOAuth = {
2467
+ pkce,
2468
+ state,
2469
+ resolve: (tokens) => {
2470
+ clearTimeout(timeout);
2471
+ resolve(tokens);
2472
+ },
2473
+ reject: (error) => {
2474
+ clearTimeout(timeout);
2475
+ reject(error);
2476
+ }
2477
+ };
2478
+ });
2479
+ }
2480
+ function maybeOpenBrowser(url) {
2481
+ try {
2482
+ if (process.platform === "darwin") {
2483
+ const child2 = child_process.spawn("open", [url], { detached: true, stdio: "ignore" });
2484
+ child2.unref();
2485
+ return;
2486
+ }
2487
+ if (process.platform === "win32") {
2488
+ const child2 = child_process.spawn("cmd", ["/c", "start", "", url], {
2489
+ detached: true,
2490
+ stdio: "ignore"
2491
+ });
2492
+ child2.unref();
2493
+ return;
2494
+ }
2495
+ const child = child_process.spawn("xdg-open", [url], { detached: true, stdio: "ignore" });
2496
+ child.unref();
2497
+ } catch {
2498
+ }
2499
+ }
2500
+ async function startCodexOAuth() {
2501
+ if (pendingOAuth) {
2502
+ throw new Error("Codex authorization is already in progress");
2503
+ }
2504
+ const { redirectUri } = await startOAuthServer();
2505
+ const pkce = await generatePKCE();
2506
+ const state = generateState();
2507
+ const authUrl = buildAuthorizeUrl(redirectUri, pkce, state);
2508
+ maybeOpenBrowser(authUrl);
2509
+ return {
2510
+ authUrl,
2511
+ waitForCallback: async () => {
2512
+ try {
2513
+ const tokens = await waitForOAuthCallback(pkce, state);
2514
+ const accountId = extractAccountId(tokens);
2515
+ if (!accountId) {
2516
+ throw new Error("Could not determine ChatGPT account ID from OAuth token");
2517
+ }
2518
+ const credentials = {
2519
+ accessToken: tokens.access_token,
2520
+ refreshToken: tokens.refresh_token,
2521
+ accountId,
2522
+ expiresAt: Date.now() + (tokens.expires_in ?? 3600) * 1e3
2523
+ };
2524
+ saveCredentials(credentials);
2525
+ return credentials;
2526
+ } finally {
2527
+ stopOAuthServer();
2528
+ }
2529
+ }
2530
+ };
2531
+ }
2532
+ async function getCodexTokens() {
2533
+ const credentials = readCredentials();
2534
+ if (!credentials) {
2535
+ throw new Error("Codex is not authenticated");
2536
+ }
2537
+ const needsRefresh = credentials.expiresAt <= Date.now() + REFRESH_BUFFER_MS;
2538
+ if (!needsRefresh) {
2539
+ return { accessToken: credentials.accessToken, accountId: credentials.accountId };
2540
+ }
2541
+ const refreshed = await refreshAccessToken(credentials.refreshToken);
2542
+ const nextAccountId = extractAccountId(refreshed) || credentials.accountId;
2543
+ const nextCredentials = {
2544
+ accessToken: refreshed.access_token,
2545
+ refreshToken: refreshed.refresh_token || credentials.refreshToken,
2546
+ accountId: nextAccountId,
2547
+ expiresAt: Date.now() + (refreshed.expires_in ?? 3600) * 1e3
2548
+ };
2549
+ saveCredentials(nextCredentials);
2550
+ return { accessToken: nextCredentials.accessToken, accountId: nextCredentials.accountId };
2551
+ }
2552
+ async function getCodexStatus() {
2553
+ const credentials = readCredentials();
2554
+ if (!credentials) {
2555
+ return { authenticated: false };
2556
+ }
2557
+ if (credentials.expiresAt > Date.now() + REFRESH_BUFFER_MS) {
2558
+ return { authenticated: true };
2559
+ }
2560
+ try {
2561
+ await getCodexTokens();
2562
+ return { authenticated: true };
2563
+ } catch {
2564
+ return { authenticated: false };
2565
+ }
2566
+ }
2567
+ async function codexLogout() {
2568
+ pendingOAuth = void 0;
2569
+ stopOAuthServer();
2570
+ if (fs10__default.default.existsSync(CREDENTIALS_PATH2)) {
2571
+ fs10__default.default.unlinkSync(CREDENTIALS_PATH2);
2572
+ }
2573
+ }
2184
2574
 
2185
2575
  // src/lib/rpc-handlers.ts
2186
2576
  var rpcHandlers = {
@@ -2329,6 +2719,23 @@ var rpcHandlers = {
2329
2719
  }
2330
2720
  const diff = await Snapshot.diff(projectId, hash);
2331
2721
  return { success: true, diff };
2722
+ },
2723
+ "daemon:codex_start_auth": async () => {
2724
+ const { authUrl, waitForCallback } = await startCodexOAuth();
2725
+ void waitForCallback().catch((error) => {
2726
+ console.error("[codex] OAuth callback failed:", error);
2727
+ });
2728
+ return { authUrl };
2729
+ },
2730
+ "daemon:codex_get_tokens": async () => {
2731
+ return getCodexTokens();
2732
+ },
2733
+ "daemon:codex_status": async () => {
2734
+ return getCodexStatus();
2735
+ },
2736
+ "daemon:codex_logout": async () => {
2737
+ await codexLogout();
2738
+ return { success: true };
2332
2739
  }
2333
2740
  };
2334
2741
  var INITIAL_RECONNECT_DELAY = 1e3;
@@ -2825,20 +3232,20 @@ function getCodeServerBin() {
2825
3232
  }
2826
3233
  function isCodeServerInstalled() {
2827
3234
  const binPath = getCodeServerBin();
2828
- return fs9__default.default.existsSync(binPath);
3235
+ return fs10__default.default.existsSync(binPath);
2829
3236
  }
2830
3237
  async function installCodeServer() {
2831
3238
  const { ext } = getPlatformInfo();
2832
3239
  const downloadUrl = getDownloadUrl();
2833
3240
  const tarballPath = path10__default.default.join(AMA_DIR, `code-server.${ext}`);
2834
- if (!fs9__default.default.existsSync(AMA_DIR)) {
2835
- fs9__default.default.mkdirSync(AMA_DIR, { recursive: true });
3241
+ if (!fs10__default.default.existsSync(AMA_DIR)) {
3242
+ fs10__default.default.mkdirSync(AMA_DIR, { recursive: true });
2836
3243
  }
2837
- if (!fs9__default.default.existsSync(CODE_DIR)) {
2838
- fs9__default.default.mkdirSync(CODE_DIR, { recursive: true });
3244
+ if (!fs10__default.default.existsSync(CODE_DIR)) {
3245
+ fs10__default.default.mkdirSync(CODE_DIR, { recursive: true });
2839
3246
  }
2840
- if (!fs9__default.default.existsSync(STORAGE_DIR)) {
2841
- fs9__default.default.mkdirSync(STORAGE_DIR, { recursive: true });
3247
+ if (!fs10__default.default.existsSync(STORAGE_DIR)) {
3248
+ fs10__default.default.mkdirSync(STORAGE_DIR, { recursive: true });
2842
3249
  }
2843
3250
  console.log(pc5__default.default.cyan(`downloading code-server v${CODE_SERVER_VERSION}...`));
2844
3251
  console.log(pc5__default.default.gray(downloadUrl));
@@ -2847,13 +3254,13 @@ async function installCodeServer() {
2847
3254
  throw new Error(`Failed to download code-server: ${response.statusText}`);
2848
3255
  }
2849
3256
  const buffer = await response.arrayBuffer();
2850
- await fs9__default.default.promises.writeFile(tarballPath, Buffer.from(buffer));
3257
+ await fs10__default.default.promises.writeFile(tarballPath, Buffer.from(buffer));
2851
3258
  console.log(pc5__default.default.cyan("Extracting code-server..."));
2852
3259
  await execAsync2(`tar -xzf ${tarballPath} -C ${CODE_DIR}`);
2853
- await fs9__default.default.promises.unlink(tarballPath);
3260
+ await fs10__default.default.promises.unlink(tarballPath);
2854
3261
  const binPath = getCodeServerBin();
2855
- if (fs9__default.default.existsSync(binPath)) {
2856
- await fs9__default.default.promises.chmod(binPath, 493);
3262
+ if (fs10__default.default.existsSync(binPath)) {
3263
+ await fs10__default.default.promises.chmod(binPath, 493);
2857
3264
  }
2858
3265
  console.log(pc5__default.default.green("code-server installed successfully"));
2859
3266
  }
@@ -2878,8 +3285,8 @@ async function killExistingCodeServer() {
2878
3285
  async function setupDefaultSettings() {
2879
3286
  const userDir = path10__default.default.join(STORAGE_DIR, "User");
2880
3287
  const settingsPath = path10__default.default.join(userDir, "settings.json");
2881
- if (!fs9__default.default.existsSync(userDir)) {
2882
- fs9__default.default.mkdirSync(userDir, { recursive: true });
3288
+ if (!fs10__default.default.existsSync(userDir)) {
3289
+ fs10__default.default.mkdirSync(userDir, { recursive: true });
2883
3290
  }
2884
3291
  const defaultSettings = {
2885
3292
  // Disable signature verification for Open VSX extensions
@@ -2897,9 +3304,9 @@ async function setupDefaultSettings() {
2897
3304
  "workbench.activityBar.location": "top"
2898
3305
  };
2899
3306
  let existingSettings = {};
2900
- if (fs9__default.default.existsSync(settingsPath)) {
3307
+ if (fs10__default.default.existsSync(settingsPath)) {
2901
3308
  try {
2902
- const content = await fs9__default.default.promises.readFile(settingsPath, "utf-8");
3309
+ const content = await fs10__default.default.promises.readFile(settingsPath, "utf-8");
2903
3310
  existingSettings = JSON.parse(content);
2904
3311
  } catch {
2905
3312
  }
@@ -2907,7 +3314,7 @@ async function setupDefaultSettings() {
2907
3314
  const mergedSettings = { ...defaultSettings, ...existingSettings };
2908
3315
  mergedSettings["workbench.colorTheme"] = "Min Dark";
2909
3316
  mergedSettings["extensions.verifySignature"] = false;
2910
- await fs9__default.default.promises.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
3317
+ await fs10__default.default.promises.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
2911
3318
  console.log(pc5__default.default.green("ama code-server settings configured"));
2912
3319
  }
2913
3320
  async function installExtensions() {
@@ -2928,7 +3335,7 @@ async function installExtensions() {
2928
3335
  async function startCodeServer(cwd) {
2929
3336
  const binPath = getCodeServerBin();
2930
3337
  const workDir = cwd || process.cwd();
2931
- if (!fs9__default.default.existsSync(binPath)) {
3338
+ if (!fs10__default.default.existsSync(binPath)) {
2932
3339
  throw new Error("ama code-server is not installed. Run installCodeServer() first.");
2933
3340
  }
2934
3341
  await killExistingCodeServer();
@@ -2936,12 +3343,12 @@ async function startCodeServer(cwd) {
2936
3343
  await installExtensions();
2937
3344
  const workspaceStoragePath = path10__default.default.join(STORAGE_DIR, "User", "workspaceStorage");
2938
3345
  try {
2939
- if (fs9__default.default.existsSync(workspaceStoragePath)) {
2940
- await fs9__default.default.promises.rm(workspaceStoragePath, { recursive: true, force: true });
3346
+ if (fs10__default.default.existsSync(workspaceStoragePath)) {
3347
+ await fs10__default.default.promises.rm(workspaceStoragePath, { recursive: true, force: true });
2941
3348
  }
2942
3349
  const stateDbPath = path10__default.default.join(STORAGE_DIR, "User", "globalStorage", "state.vscdb");
2943
- if (fs9__default.default.existsSync(stateDbPath)) {
2944
- await fs9__default.default.promises.unlink(stateDbPath);
3350
+ if (fs10__default.default.existsSync(stateDbPath)) {
3351
+ await fs10__default.default.promises.unlink(stateDbPath);
2945
3352
  }
2946
3353
  } catch {
2947
3354
  }
@@ -2972,11 +3379,11 @@ var __dirname$1 = path10.dirname(__filename$1);
2972
3379
  var DAEMON_PID_FILE = path10__default.default.join(AMA_DIR, "daemon.pid");
2973
3380
  var DAEMON_LOG_FILE = path10__default.default.join(AMA_DIR, "daemon.log");
2974
3381
  function isDaemonRunning() {
2975
- if (!fs9__default.default.existsSync(DAEMON_PID_FILE)) {
3382
+ if (!fs10__default.default.existsSync(DAEMON_PID_FILE)) {
2976
3383
  return false;
2977
3384
  }
2978
3385
  try {
2979
- const pid = Number(fs9__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
3386
+ const pid = Number(fs10__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2980
3387
  process.kill(pid, 0);
2981
3388
  return true;
2982
3389
  } catch {
@@ -2984,30 +3391,30 @@ function isDaemonRunning() {
2984
3391
  }
2985
3392
  }
2986
3393
  function stopDaemon() {
2987
- if (!fs9__default.default.existsSync(DAEMON_PID_FILE)) {
3394
+ if (!fs10__default.default.existsSync(DAEMON_PID_FILE)) {
2988
3395
  return false;
2989
3396
  }
2990
3397
  try {
2991
- const pid = Number(fs9__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
3398
+ const pid = Number(fs10__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2992
3399
  process.kill(pid, "SIGTERM");
2993
- fs9__default.default.unlinkSync(DAEMON_PID_FILE);
3400
+ fs10__default.default.unlinkSync(DAEMON_PID_FILE);
2994
3401
  return true;
2995
3402
  } catch (error) {
2996
3403
  return false;
2997
3404
  }
2998
3405
  }
2999
3406
  function startDaemon() {
3000
- if (!fs9__default.default.existsSync(AMA_DIR)) {
3001
- fs9__default.default.mkdirSync(AMA_DIR, { recursive: true });
3407
+ if (!fs10__default.default.existsSync(AMA_DIR)) {
3408
+ fs10__default.default.mkdirSync(AMA_DIR, { recursive: true });
3002
3409
  }
3003
3410
  if (isDaemonRunning()) {
3004
3411
  stopDaemon();
3005
3412
  }
3006
3413
  const daemonScript = path10__default.default.join(__dirname$1, "lib", "daemon-entry.js");
3007
- if (!fs9__default.default.existsSync(daemonScript)) {
3414
+ if (!fs10__default.default.existsSync(daemonScript)) {
3008
3415
  throw new Error(`Daemon entry script not found at: ${daemonScript}. Please rebuild the project.`);
3009
3416
  }
3010
- const logFd = fs9__default.default.openSync(DAEMON_LOG_FILE, "a");
3417
+ const logFd = fs10__default.default.openSync(DAEMON_LOG_FILE, "a");
3011
3418
  const daemon = child_process.spawn(process.execPath, [daemonScript], {
3012
3419
  detached: true,
3013
3420
  stdio: ["ignore", logFd, logFd],
@@ -3015,20 +3422,20 @@ function startDaemon() {
3015
3422
  cwd: process.cwd()
3016
3423
  });
3017
3424
  daemon.unref();
3018
- fs9__default.default.writeFileSync(DAEMON_PID_FILE, String(daemon.pid));
3019
- fs9__default.default.closeSync(logFd);
3425
+ fs10__default.default.writeFileSync(DAEMON_PID_FILE, String(daemon.pid));
3426
+ fs10__default.default.closeSync(logFd);
3020
3427
  }
3021
3428
  function getDaemonPid() {
3022
- if (!fs9__default.default.existsSync(DAEMON_PID_FILE)) {
3429
+ if (!fs10__default.default.existsSync(DAEMON_PID_FILE)) {
3023
3430
  return null;
3024
3431
  }
3025
3432
  try {
3026
- return Number(fs9__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
3433
+ return Number(fs10__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
3027
3434
  } catch {
3028
3435
  return null;
3029
3436
  }
3030
3437
  }
3031
- var VERSION = "0.0.17";
3438
+ var VERSION = "0.0.18";
3032
3439
  var PROJECT_DIR = process.cwd();
3033
3440
  var LOGO = `
3034
3441
  __ _ _ __ ___ __ _
@@ -3108,6 +3515,9 @@ if (args[0] === "--help" || args[0] === "-h") {
3108
3515
  console.log("");
3109
3516
  console.log(pc5__default.default.cyan(" commands"));
3110
3517
  console.log(pc5__default.default.gray(" login authenticate with amai"));
3518
+ console.log(pc5__default.default.gray(" codex connect ChatGPT subscription for Codex"));
3519
+ console.log(pc5__default.default.gray(" codex status check Codex auth status"));
3520
+ console.log(pc5__default.default.gray(" codex logout remove Codex credentials"));
3111
3521
  console.log(pc5__default.default.gray(" logout remove credentials"));
3112
3522
  console.log(pc5__default.default.gray(" start start background daemon"));
3113
3523
  console.log(pc5__default.default.gray(" stop stop background daemon"));
@@ -3144,6 +3554,33 @@ if (args[0] === "update") {
3144
3554
  }
3145
3555
  process.exit(0);
3146
3556
  })();
3557
+ } else if (args[0] === "codex") {
3558
+ (async () => {
3559
+ try {
3560
+ const subCommand = args[1];
3561
+ if (subCommand === "status") {
3562
+ const status = await getCodexStatus();
3563
+ console.log(pc5__default.default.gray(`codex auth: ${status.authenticated ? "connected" : "not connected"}`));
3564
+ process.exit(0);
3565
+ }
3566
+ if (subCommand === "logout") {
3567
+ await codexLogout();
3568
+ console.log(pc5__default.default.cyan("codex credentials removed"));
3569
+ process.exit(0);
3570
+ }
3571
+ console.log(pc5__default.default.gray("starting codex auth..."));
3572
+ const { authUrl, waitForCallback } = await startCodexOAuth();
3573
+ console.log("");
3574
+ console.log(pc5__default.default.cyan(`open: ${authUrl}`));
3575
+ console.log(pc5__default.default.gray("complete authorization in your browser..."));
3576
+ const result = await waitForCallback();
3577
+ console.log(pc5__default.default.cyan(`codex connected (account: ${result.accountId})`));
3578
+ process.exit(0);
3579
+ } catch (error) {
3580
+ console.error(pc5__default.default.red(error.message || "codex auth failed"));
3581
+ process.exit(1);
3582
+ }
3583
+ })();
3147
3584
  } else if (args[0] === "start") {
3148
3585
  (async () => {
3149
3586
  if (isDaemonRunning()) {
@@ -3195,11 +3632,11 @@ if (args[0] === "update") {
3195
3632
  process.exit(1);
3196
3633
  }
3197
3634
  const resolvedPath = path10__default.default.resolve(projectPath);
3198
- if (!fs9__default.default.existsSync(resolvedPath)) {
3635
+ if (!fs10__default.default.existsSync(resolvedPath)) {
3199
3636
  console.error(pc5__default.default.red(`path does not exist: ${resolvedPath}`));
3200
3637
  process.exit(1);
3201
3638
  }
3202
- if (!fs9__default.default.statSync(resolvedPath).isDirectory()) {
3639
+ if (!fs10__default.default.statSync(resolvedPath).isDirectory()) {
3203
3640
  console.error(pc5__default.default.red(`path is not a directory: ${resolvedPath}`));
3204
3641
  process.exit(1);
3205
3642
  }