amai 0.0.22 → 0.0.23

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/README.md CHANGED
@@ -67,7 +67,7 @@ amai [command] [options]
67
67
  ### Environment Variables
68
68
 
69
69
  - `SERVER_URL` - WebSocket server URL to connect to (optional, has a default)
70
- - Example: `ws://localhost:3000` or `wss://your-server.com`
70
+ - Example: `ws://localhost:8787` or `wss://your-server.com`
71
71
 
72
72
  ### Examples
73
73
 
package/dist/cli.cjs CHANGED
@@ -29,8 +29,8 @@ var fs7__default = /*#__PURE__*/_interopDefault(fs7);
29
29
  var fs5__default = /*#__PURE__*/_interopDefault(fs5);
30
30
  var readline__default = /*#__PURE__*/_interopDefault(readline);
31
31
 
32
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
33
- var CLIENT_ID = "client_01K4Y8A67H544Z6J8A47E5GJ9A";
32
+ var DEFAULT_SERVER_URL = process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
33
+ var CLIENT_ID = "client_01K4Y8A5Q3FYGXD362BJQ6AGYD";
34
34
  var AMA_DIR = path6__default.default.join(os3__default.default.homedir(), ".amai");
35
35
  var CODE_DIR = path6__default.default.join(AMA_DIR, "code");
36
36
  var STORAGE_DIR = path6__default.default.join(AMA_DIR, "storage");
@@ -750,6 +750,7 @@ var Snapshot;
750
750
  })(Snapshot || (Snapshot = {}));
751
751
  var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
752
752
  var ISSUER = "https://auth.openai.com";
753
+ var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
753
754
  var OAUTH_PORT = 1455;
754
755
  var CREDENTIALS_PATH2 = path6__default.default.join(AMA_DIR, "codex-credentials.json");
755
756
  var CALLBACK_PATH = "/auth/callback";
@@ -1141,6 +1142,30 @@ async function getCodexStatus() {
1141
1142
  return { authenticated: false };
1142
1143
  }
1143
1144
  }
1145
+ async function codexFetch(body) {
1146
+ const { accessToken, accountId } = await getCodexTokens();
1147
+ const response = await fetch(CODEX_API_ENDPOINT, {
1148
+ method: "POST",
1149
+ headers: {
1150
+ "Content-Type": "application/json",
1151
+ Authorization: `Bearer ${accessToken}`,
1152
+ "ChatGPT-Account-Id": accountId,
1153
+ originator: "ama",
1154
+ Accept: "text/event-stream"
1155
+ },
1156
+ body
1157
+ });
1158
+ const text = await response.text();
1159
+ const headers = {};
1160
+ response.headers.forEach((value, key) => {
1161
+ headers[key] = value;
1162
+ });
1163
+ return {
1164
+ status: response.status,
1165
+ headers,
1166
+ body: text
1167
+ };
1168
+ }
1144
1169
  async function codexLogout() {
1145
1170
  pendingOAuth = void 0;
1146
1171
  stopOAuthServer();
@@ -1307,6 +1332,16 @@ var rpcHandlers = {
1307
1332
  "daemon:codex_get_tokens": async () => {
1308
1333
  return getCodexTokens();
1309
1334
  },
1335
+ "daemon:codex_fetch": async ({ body }) => {
1336
+ if (typeof body !== "string" || !body.trim()) {
1337
+ const error = {
1338
+ _tag: "ValidationError",
1339
+ message: "body is required"
1340
+ };
1341
+ throw error;
1342
+ }
1343
+ return codexFetch(body);
1344
+ },
1310
1345
  "daemon:codex_status": async () => {
1311
1346
  return getCodexStatus();
1312
1347
  },
@@ -1318,8 +1353,10 @@ var rpcHandlers = {
1318
1353
  var INITIAL_RECONNECT_DELAY = 1e3;
1319
1354
  var MAX_RECONNECT_DELAY = 6e4;
1320
1355
  var BACKOFF_MULTIPLIER = 2;
1356
+ var CLI_HEARTBEAT_INTERVAL_MS = 5e3;
1321
1357
  var reconnectTimeout = null;
1322
1358
  var reconnectAttempts = 0;
1359
+ var heartbeatInterval = null;
1323
1360
  function getReconnectDelay() {
1324
1361
  const delay = Math.min(
1325
1362
  INITIAL_RECONNECT_DELAY * Math.pow(BACKOFF_MULTIPLIER, reconnectAttempts),
@@ -1347,6 +1384,19 @@ var connectToUserStreams = async (serverUrl) => {
1347
1384
  Authorization: `Bearer ${tokens.access_token}`
1348
1385
  }
1349
1386
  });
1387
+ const clearHeartbeat = () => {
1388
+ if (heartbeatInterval) {
1389
+ clearInterval(heartbeatInterval);
1390
+ heartbeatInterval = null;
1391
+ }
1392
+ };
1393
+ const sendHeartbeat = () => {
1394
+ if (ws.readyState !== WebSocket__default.default.OPEN) return;
1395
+ ws.send(JSON.stringify({
1396
+ _tag: "cli_heartbeat",
1397
+ timestamp: Date.now()
1398
+ }));
1399
+ };
1350
1400
  ws.on("open", () => {
1351
1401
  reconnectAttempts = 0;
1352
1402
  console.log(pc5__default.default.cyan("connected to user streams"));
@@ -1354,6 +1404,9 @@ var connectToUserStreams = async (serverUrl) => {
1354
1404
  clearTimeout(reconnectTimeout);
1355
1405
  reconnectTimeout = null;
1356
1406
  }
1407
+ clearHeartbeat();
1408
+ sendHeartbeat();
1409
+ heartbeatInterval = setInterval(sendHeartbeat, CLI_HEARTBEAT_INTERVAL_MS);
1357
1410
  });
1358
1411
  ws.on("message", async (event) => {
1359
1412
  try {
@@ -1413,6 +1466,7 @@ var connectToUserStreams = async (serverUrl) => {
1413
1466
  }
1414
1467
  });
1415
1468
  ws.on("close", (code, reason) => {
1469
+ clearHeartbeat();
1416
1470
  const delay = getReconnectDelay();
1417
1471
  reconnectAttempts++;
1418
1472
  console.log(pc5__default.default.gray(`user streams disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
@@ -1423,6 +1477,7 @@ var connectToUserStreams = async (serverUrl) => {
1423
1477
  }, delay);
1424
1478
  });
1425
1479
  ws.on("error", (error) => {
1480
+ clearHeartbeat();
1426
1481
  console.error(pc5__default.default.red(`stream error: ${error.message}`));
1427
1482
  });
1428
1483
  return ws;
@@ -1909,7 +1964,7 @@ function getDaemonPid() {
1909
1964
  return null;
1910
1965
  }
1911
1966
  }
1912
- var VERSION = "0.0.22";
1967
+ var VERSION = "0.0.23";
1913
1968
  var PROJECT_DIR = process.cwd();
1914
1969
  var LOGO = `
1915
1970
  __ _ _ __ ___ __ _
package/dist/cli.js CHANGED
@@ -16,8 +16,8 @@ import { batchTool, bashTool, apply_patch, read_file, list, globTool, grepTool,
16
16
  import { fileURLToPath } from 'url';
17
17
  import readline from 'readline';
18
18
 
19
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
20
- var CLIENT_ID = "client_01K4Y8A67H544Z6J8A47E5GJ9A";
19
+ var DEFAULT_SERVER_URL = process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
20
+ var CLIENT_ID = "client_01K4Y8A5Q3FYGXD362BJQ6AGYD";
21
21
  var AMA_DIR = path6.join(os3.homedir(), ".amai");
22
22
  var CODE_DIR = path6.join(AMA_DIR, "code");
23
23
  var STORAGE_DIR = path6.join(AMA_DIR, "storage");
@@ -737,6 +737,7 @@ var Snapshot;
737
737
  })(Snapshot || (Snapshot = {}));
738
738
  var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
739
739
  var ISSUER = "https://auth.openai.com";
740
+ var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
740
741
  var OAUTH_PORT = 1455;
741
742
  var CREDENTIALS_PATH2 = path6.join(AMA_DIR, "codex-credentials.json");
742
743
  var CALLBACK_PATH = "/auth/callback";
@@ -1128,6 +1129,30 @@ async function getCodexStatus() {
1128
1129
  return { authenticated: false };
1129
1130
  }
1130
1131
  }
1132
+ async function codexFetch(body) {
1133
+ const { accessToken, accountId } = await getCodexTokens();
1134
+ const response = await fetch(CODEX_API_ENDPOINT, {
1135
+ method: "POST",
1136
+ headers: {
1137
+ "Content-Type": "application/json",
1138
+ Authorization: `Bearer ${accessToken}`,
1139
+ "ChatGPT-Account-Id": accountId,
1140
+ originator: "ama",
1141
+ Accept: "text/event-stream"
1142
+ },
1143
+ body
1144
+ });
1145
+ const text = await response.text();
1146
+ const headers = {};
1147
+ response.headers.forEach((value, key) => {
1148
+ headers[key] = value;
1149
+ });
1150
+ return {
1151
+ status: response.status,
1152
+ headers,
1153
+ body: text
1154
+ };
1155
+ }
1131
1156
  async function codexLogout() {
1132
1157
  pendingOAuth = void 0;
1133
1158
  stopOAuthServer();
@@ -1294,6 +1319,16 @@ var rpcHandlers = {
1294
1319
  "daemon:codex_get_tokens": async () => {
1295
1320
  return getCodexTokens();
1296
1321
  },
1322
+ "daemon:codex_fetch": async ({ body }) => {
1323
+ if (typeof body !== "string" || !body.trim()) {
1324
+ const error = {
1325
+ _tag: "ValidationError",
1326
+ message: "body is required"
1327
+ };
1328
+ throw error;
1329
+ }
1330
+ return codexFetch(body);
1331
+ },
1297
1332
  "daemon:codex_status": async () => {
1298
1333
  return getCodexStatus();
1299
1334
  },
@@ -1305,8 +1340,10 @@ var rpcHandlers = {
1305
1340
  var INITIAL_RECONNECT_DELAY = 1e3;
1306
1341
  var MAX_RECONNECT_DELAY = 6e4;
1307
1342
  var BACKOFF_MULTIPLIER = 2;
1343
+ var CLI_HEARTBEAT_INTERVAL_MS = 5e3;
1308
1344
  var reconnectTimeout = null;
1309
1345
  var reconnectAttempts = 0;
1346
+ var heartbeatInterval = null;
1310
1347
  function getReconnectDelay() {
1311
1348
  const delay = Math.min(
1312
1349
  INITIAL_RECONNECT_DELAY * Math.pow(BACKOFF_MULTIPLIER, reconnectAttempts),
@@ -1334,6 +1371,19 @@ var connectToUserStreams = async (serverUrl) => {
1334
1371
  Authorization: `Bearer ${tokens.access_token}`
1335
1372
  }
1336
1373
  });
1374
+ const clearHeartbeat = () => {
1375
+ if (heartbeatInterval) {
1376
+ clearInterval(heartbeatInterval);
1377
+ heartbeatInterval = null;
1378
+ }
1379
+ };
1380
+ const sendHeartbeat = () => {
1381
+ if (ws.readyState !== WebSocket.OPEN) return;
1382
+ ws.send(JSON.stringify({
1383
+ _tag: "cli_heartbeat",
1384
+ timestamp: Date.now()
1385
+ }));
1386
+ };
1337
1387
  ws.on("open", () => {
1338
1388
  reconnectAttempts = 0;
1339
1389
  console.log(pc5.cyan("connected to user streams"));
@@ -1341,6 +1391,9 @@ var connectToUserStreams = async (serverUrl) => {
1341
1391
  clearTimeout(reconnectTimeout);
1342
1392
  reconnectTimeout = null;
1343
1393
  }
1394
+ clearHeartbeat();
1395
+ sendHeartbeat();
1396
+ heartbeatInterval = setInterval(sendHeartbeat, CLI_HEARTBEAT_INTERVAL_MS);
1344
1397
  });
1345
1398
  ws.on("message", async (event) => {
1346
1399
  try {
@@ -1400,6 +1453,7 @@ var connectToUserStreams = async (serverUrl) => {
1400
1453
  }
1401
1454
  });
1402
1455
  ws.on("close", (code, reason) => {
1456
+ clearHeartbeat();
1403
1457
  const delay = getReconnectDelay();
1404
1458
  reconnectAttempts++;
1405
1459
  console.log(pc5.gray(`user streams disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
@@ -1410,6 +1464,7 @@ var connectToUserStreams = async (serverUrl) => {
1410
1464
  }, delay);
1411
1465
  });
1412
1466
  ws.on("error", (error) => {
1467
+ clearHeartbeat();
1413
1468
  console.error(pc5.red(`stream error: ${error.message}`));
1414
1469
  });
1415
1470
  return ws;
@@ -1896,7 +1951,7 @@ function getDaemonPid() {
1896
1951
  return null;
1897
1952
  }
1898
1953
  }
1899
- var VERSION = "0.0.22";
1954
+ var VERSION = "0.0.23";
1900
1955
  var PROJECT_DIR = process.cwd();
1901
1956
  var LOGO = `
1902
1957
  __ _ _ __ ___ __ _
@@ -15,6 +15,7 @@ var path2__default = /*#__PURE__*/_interopDefault(path2);
15
15
  var pc__default = /*#__PURE__*/_interopDefault(pc);
16
16
  var os__default = /*#__PURE__*/_interopDefault(os);
17
17
 
18
+ process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
18
19
  var AMA_DIR = path2__default.default.join(os__default.default.homedir(), ".amai");
19
20
  var CODE_DIR = path2__default.default.join(AMA_DIR, "code");
20
21
  var STORAGE_DIR = path2__default.default.join(AMA_DIR, "storage");
@@ -6,6 +6,7 @@ import path2 from 'path';
6
6
  import pc from 'picocolors';
7
7
  import os from 'os';
8
8
 
9
+ process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
9
10
  var AMA_DIR = path2.join(os.homedir(), ".amai");
10
11
  var CODE_DIR = path2.join(AMA_DIR, "code");
11
12
  var STORAGE_DIR = path2.join(AMA_DIR, "storage");
@@ -25,7 +25,7 @@ var pc3__default = /*#__PURE__*/_interopDefault(pc3);
25
25
  var fs7__default = /*#__PURE__*/_interopDefault(fs7);
26
26
  var fs5__default = /*#__PURE__*/_interopDefault(fs5);
27
27
 
28
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
28
+ var DEFAULT_SERVER_URL = process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
29
29
  var AMA_DIR = path6__default.default.join(os3__default.default.homedir(), ".amai");
30
30
  var CODE_DIR = path6__default.default.join(AMA_DIR, "code");
31
31
  var STORAGE_DIR = path6__default.default.join(AMA_DIR, "storage");
@@ -616,6 +616,7 @@ var Snapshot;
616
616
  })(Snapshot || (Snapshot = {}));
617
617
  var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
618
618
  var ISSUER = "https://auth.openai.com";
619
+ var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
619
620
  var OAUTH_PORT = 1455;
620
621
  var CREDENTIALS_PATH2 = path6__default.default.join(AMA_DIR, "codex-credentials.json");
621
622
  var CALLBACK_PATH = "/auth/callback";
@@ -1007,6 +1008,30 @@ async function getCodexStatus() {
1007
1008
  return { authenticated: false };
1008
1009
  }
1009
1010
  }
1011
+ async function codexFetch(body) {
1012
+ const { accessToken, accountId } = await getCodexTokens();
1013
+ const response = await fetch(CODEX_API_ENDPOINT, {
1014
+ method: "POST",
1015
+ headers: {
1016
+ "Content-Type": "application/json",
1017
+ Authorization: `Bearer ${accessToken}`,
1018
+ "ChatGPT-Account-Id": accountId,
1019
+ originator: "ama",
1020
+ Accept: "text/event-stream"
1021
+ },
1022
+ body
1023
+ });
1024
+ const text = await response.text();
1025
+ const headers = {};
1026
+ response.headers.forEach((value, key) => {
1027
+ headers[key] = value;
1028
+ });
1029
+ return {
1030
+ status: response.status,
1031
+ headers,
1032
+ body: text
1033
+ };
1034
+ }
1010
1035
  async function codexLogout() {
1011
1036
  pendingOAuth = void 0;
1012
1037
  stopOAuthServer();
@@ -1173,6 +1198,16 @@ var rpcHandlers = {
1173
1198
  "daemon:codex_get_tokens": async () => {
1174
1199
  return getCodexTokens();
1175
1200
  },
1201
+ "daemon:codex_fetch": async ({ body }) => {
1202
+ if (typeof body !== "string" || !body.trim()) {
1203
+ const error = {
1204
+ _tag: "ValidationError",
1205
+ message: "body is required"
1206
+ };
1207
+ throw error;
1208
+ }
1209
+ return codexFetch(body);
1210
+ },
1176
1211
  "daemon:codex_status": async () => {
1177
1212
  return getCodexStatus();
1178
1213
  },
@@ -1184,8 +1219,10 @@ var rpcHandlers = {
1184
1219
  var INITIAL_RECONNECT_DELAY = 1e3;
1185
1220
  var MAX_RECONNECT_DELAY = 6e4;
1186
1221
  var BACKOFF_MULTIPLIER = 2;
1222
+ var CLI_HEARTBEAT_INTERVAL_MS = 5e3;
1187
1223
  var reconnectTimeout = null;
1188
1224
  var reconnectAttempts = 0;
1225
+ var heartbeatInterval = null;
1189
1226
  function getReconnectDelay() {
1190
1227
  const delay = Math.min(
1191
1228
  INITIAL_RECONNECT_DELAY * Math.pow(BACKOFF_MULTIPLIER, reconnectAttempts),
@@ -1213,6 +1250,19 @@ var connectToUserStreams = async (serverUrl) => {
1213
1250
  Authorization: `Bearer ${tokens.access_token}`
1214
1251
  }
1215
1252
  });
1253
+ const clearHeartbeat = () => {
1254
+ if (heartbeatInterval) {
1255
+ clearInterval(heartbeatInterval);
1256
+ heartbeatInterval = null;
1257
+ }
1258
+ };
1259
+ const sendHeartbeat = () => {
1260
+ if (ws.readyState !== WebSocket__default.default.OPEN) return;
1261
+ ws.send(JSON.stringify({
1262
+ _tag: "cli_heartbeat",
1263
+ timestamp: Date.now()
1264
+ }));
1265
+ };
1216
1266
  ws.on("open", () => {
1217
1267
  reconnectAttempts = 0;
1218
1268
  console.log(pc3__default.default.cyan("connected to user streams"));
@@ -1220,6 +1270,9 @@ var connectToUserStreams = async (serverUrl) => {
1220
1270
  clearTimeout(reconnectTimeout);
1221
1271
  reconnectTimeout = null;
1222
1272
  }
1273
+ clearHeartbeat();
1274
+ sendHeartbeat();
1275
+ heartbeatInterval = setInterval(sendHeartbeat, CLI_HEARTBEAT_INTERVAL_MS);
1223
1276
  });
1224
1277
  ws.on("message", async (event) => {
1225
1278
  try {
@@ -1279,6 +1332,7 @@ var connectToUserStreams = async (serverUrl) => {
1279
1332
  }
1280
1333
  });
1281
1334
  ws.on("close", (code, reason) => {
1335
+ clearHeartbeat();
1282
1336
  const delay = getReconnectDelay();
1283
1337
  reconnectAttempts++;
1284
1338
  console.log(pc3__default.default.gray(`user streams disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
@@ -1289,6 +1343,7 @@ var connectToUserStreams = async (serverUrl) => {
1289
1343
  }, delay);
1290
1344
  });
1291
1345
  ws.on("error", (error) => {
1346
+ clearHeartbeat();
1292
1347
  console.error(pc3__default.default.red(`stream error: ${error.message}`));
1293
1348
  });
1294
1349
  return ws;
@@ -14,7 +14,7 @@ import { z } from 'zod';
14
14
  import { createServer } from 'http';
15
15
  import { batchTool, bashTool, apply_patch, read_file, list, globTool, grepTool, deleteFile, editFiles } from '@ama/agent';
16
16
 
17
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
17
+ var DEFAULT_SERVER_URL = process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
18
18
  var AMA_DIR = path6.join(os3.homedir(), ".amai");
19
19
  var CODE_DIR = path6.join(AMA_DIR, "code");
20
20
  var STORAGE_DIR = path6.join(AMA_DIR, "storage");
@@ -605,6 +605,7 @@ var Snapshot;
605
605
  })(Snapshot || (Snapshot = {}));
606
606
  var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
607
607
  var ISSUER = "https://auth.openai.com";
608
+ var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
608
609
  var OAUTH_PORT = 1455;
609
610
  var CREDENTIALS_PATH2 = path6.join(AMA_DIR, "codex-credentials.json");
610
611
  var CALLBACK_PATH = "/auth/callback";
@@ -996,6 +997,30 @@ async function getCodexStatus() {
996
997
  return { authenticated: false };
997
998
  }
998
999
  }
1000
+ async function codexFetch(body) {
1001
+ const { accessToken, accountId } = await getCodexTokens();
1002
+ const response = await fetch(CODEX_API_ENDPOINT, {
1003
+ method: "POST",
1004
+ headers: {
1005
+ "Content-Type": "application/json",
1006
+ Authorization: `Bearer ${accessToken}`,
1007
+ "ChatGPT-Account-Id": accountId,
1008
+ originator: "ama",
1009
+ Accept: "text/event-stream"
1010
+ },
1011
+ body
1012
+ });
1013
+ const text = await response.text();
1014
+ const headers = {};
1015
+ response.headers.forEach((value, key) => {
1016
+ headers[key] = value;
1017
+ });
1018
+ return {
1019
+ status: response.status,
1020
+ headers,
1021
+ body: text
1022
+ };
1023
+ }
999
1024
  async function codexLogout() {
1000
1025
  pendingOAuth = void 0;
1001
1026
  stopOAuthServer();
@@ -1162,6 +1187,16 @@ var rpcHandlers = {
1162
1187
  "daemon:codex_get_tokens": async () => {
1163
1188
  return getCodexTokens();
1164
1189
  },
1190
+ "daemon:codex_fetch": async ({ body }) => {
1191
+ if (typeof body !== "string" || !body.trim()) {
1192
+ const error = {
1193
+ _tag: "ValidationError",
1194
+ message: "body is required"
1195
+ };
1196
+ throw error;
1197
+ }
1198
+ return codexFetch(body);
1199
+ },
1165
1200
  "daemon:codex_status": async () => {
1166
1201
  return getCodexStatus();
1167
1202
  },
@@ -1173,8 +1208,10 @@ var rpcHandlers = {
1173
1208
  var INITIAL_RECONNECT_DELAY = 1e3;
1174
1209
  var MAX_RECONNECT_DELAY = 6e4;
1175
1210
  var BACKOFF_MULTIPLIER = 2;
1211
+ var CLI_HEARTBEAT_INTERVAL_MS = 5e3;
1176
1212
  var reconnectTimeout = null;
1177
1213
  var reconnectAttempts = 0;
1214
+ var heartbeatInterval = null;
1178
1215
  function getReconnectDelay() {
1179
1216
  const delay = Math.min(
1180
1217
  INITIAL_RECONNECT_DELAY * Math.pow(BACKOFF_MULTIPLIER, reconnectAttempts),
@@ -1202,6 +1239,19 @@ var connectToUserStreams = async (serverUrl) => {
1202
1239
  Authorization: `Bearer ${tokens.access_token}`
1203
1240
  }
1204
1241
  });
1242
+ const clearHeartbeat = () => {
1243
+ if (heartbeatInterval) {
1244
+ clearInterval(heartbeatInterval);
1245
+ heartbeatInterval = null;
1246
+ }
1247
+ };
1248
+ const sendHeartbeat = () => {
1249
+ if (ws.readyState !== WebSocket.OPEN) return;
1250
+ ws.send(JSON.stringify({
1251
+ _tag: "cli_heartbeat",
1252
+ timestamp: Date.now()
1253
+ }));
1254
+ };
1205
1255
  ws.on("open", () => {
1206
1256
  reconnectAttempts = 0;
1207
1257
  console.log(pc3.cyan("connected to user streams"));
@@ -1209,6 +1259,9 @@ var connectToUserStreams = async (serverUrl) => {
1209
1259
  clearTimeout(reconnectTimeout);
1210
1260
  reconnectTimeout = null;
1211
1261
  }
1262
+ clearHeartbeat();
1263
+ sendHeartbeat();
1264
+ heartbeatInterval = setInterval(sendHeartbeat, CLI_HEARTBEAT_INTERVAL_MS);
1212
1265
  });
1213
1266
  ws.on("message", async (event) => {
1214
1267
  try {
@@ -1268,6 +1321,7 @@ var connectToUserStreams = async (serverUrl) => {
1268
1321
  }
1269
1322
  });
1270
1323
  ws.on("close", (code, reason) => {
1324
+ clearHeartbeat();
1271
1325
  const delay = getReconnectDelay();
1272
1326
  reconnectAttempts++;
1273
1327
  console.log(pc3.gray(`user streams disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
@@ -1278,6 +1332,7 @@ var connectToUserStreams = async (serverUrl) => {
1278
1332
  }, delay);
1279
1333
  });
1280
1334
  ws.on("error", (error) => {
1335
+ clearHeartbeat();
1281
1336
  console.error(pc3.red(`stream error: ${error.message}`));
1282
1337
  });
1283
1338
  return ws;
package/dist/server.cjs CHANGED
@@ -25,7 +25,7 @@ var pc3__default = /*#__PURE__*/_interopDefault(pc3);
25
25
  var fs4__default = /*#__PURE__*/_interopDefault(fs4);
26
26
  var fs5__default = /*#__PURE__*/_interopDefault(fs5);
27
27
 
28
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
28
+ var DEFAULT_SERVER_URL = process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
29
29
  var AMA_DIR = path6__default.default.join(os3__default.default.homedir(), ".amai");
30
30
  path6__default.default.join(AMA_DIR, "code");
31
31
  path6__default.default.join(AMA_DIR, "storage");
@@ -616,6 +616,7 @@ var Snapshot;
616
616
  })(Snapshot || (Snapshot = {}));
617
617
  var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
618
618
  var ISSUER = "https://auth.openai.com";
619
+ var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
619
620
  var OAUTH_PORT = 1455;
620
621
  var CREDENTIALS_PATH2 = path6__default.default.join(AMA_DIR, "codex-credentials.json");
621
622
  var CALLBACK_PATH = "/auth/callback";
@@ -1007,6 +1008,30 @@ async function getCodexStatus() {
1007
1008
  return { authenticated: false };
1008
1009
  }
1009
1010
  }
1011
+ async function codexFetch(body) {
1012
+ const { accessToken, accountId } = await getCodexTokens();
1013
+ const response = await fetch(CODEX_API_ENDPOINT, {
1014
+ method: "POST",
1015
+ headers: {
1016
+ "Content-Type": "application/json",
1017
+ Authorization: `Bearer ${accessToken}`,
1018
+ "ChatGPT-Account-Id": accountId,
1019
+ originator: "ama",
1020
+ Accept: "text/event-stream"
1021
+ },
1022
+ body
1023
+ });
1024
+ const text = await response.text();
1025
+ const headers = {};
1026
+ response.headers.forEach((value, key) => {
1027
+ headers[key] = value;
1028
+ });
1029
+ return {
1030
+ status: response.status,
1031
+ headers,
1032
+ body: text
1033
+ };
1034
+ }
1010
1035
  async function codexLogout() {
1011
1036
  pendingOAuth = void 0;
1012
1037
  stopOAuthServer();
@@ -1173,6 +1198,16 @@ var rpcHandlers = {
1173
1198
  "daemon:codex_get_tokens": async () => {
1174
1199
  return getCodexTokens();
1175
1200
  },
1201
+ "daemon:codex_fetch": async ({ body }) => {
1202
+ if (typeof body !== "string" || !body.trim()) {
1203
+ const error = {
1204
+ _tag: "ValidationError",
1205
+ message: "body is required"
1206
+ };
1207
+ throw error;
1208
+ }
1209
+ return codexFetch(body);
1210
+ },
1176
1211
  "daemon:codex_status": async () => {
1177
1212
  return getCodexStatus();
1178
1213
  },
@@ -1184,8 +1219,10 @@ var rpcHandlers = {
1184
1219
  var INITIAL_RECONNECT_DELAY = 1e3;
1185
1220
  var MAX_RECONNECT_DELAY = 6e4;
1186
1221
  var BACKOFF_MULTIPLIER = 2;
1222
+ var CLI_HEARTBEAT_INTERVAL_MS = 5e3;
1187
1223
  var reconnectTimeout = null;
1188
1224
  var reconnectAttempts = 0;
1225
+ var heartbeatInterval = null;
1189
1226
  function getReconnectDelay() {
1190
1227
  const delay = Math.min(
1191
1228
  INITIAL_RECONNECT_DELAY * Math.pow(BACKOFF_MULTIPLIER, reconnectAttempts),
@@ -1213,6 +1250,19 @@ var connectToUserStreams = async (serverUrl) => {
1213
1250
  Authorization: `Bearer ${tokens.access_token}`
1214
1251
  }
1215
1252
  });
1253
+ const clearHeartbeat = () => {
1254
+ if (heartbeatInterval) {
1255
+ clearInterval(heartbeatInterval);
1256
+ heartbeatInterval = null;
1257
+ }
1258
+ };
1259
+ const sendHeartbeat = () => {
1260
+ if (ws.readyState !== WebSocket2__default.default.OPEN) return;
1261
+ ws.send(JSON.stringify({
1262
+ _tag: "cli_heartbeat",
1263
+ timestamp: Date.now()
1264
+ }));
1265
+ };
1216
1266
  ws.on("open", () => {
1217
1267
  reconnectAttempts = 0;
1218
1268
  console.log(pc3__default.default.cyan("connected to user streams"));
@@ -1220,6 +1270,9 @@ var connectToUserStreams = async (serverUrl) => {
1220
1270
  clearTimeout(reconnectTimeout);
1221
1271
  reconnectTimeout = null;
1222
1272
  }
1273
+ clearHeartbeat();
1274
+ sendHeartbeat();
1275
+ heartbeatInterval = setInterval(sendHeartbeat, CLI_HEARTBEAT_INTERVAL_MS);
1223
1276
  });
1224
1277
  ws.on("message", async (event) => {
1225
1278
  try {
@@ -1279,6 +1332,7 @@ var connectToUserStreams = async (serverUrl) => {
1279
1332
  }
1280
1333
  });
1281
1334
  ws.on("close", (code, reason) => {
1335
+ clearHeartbeat();
1282
1336
  const delay = getReconnectDelay();
1283
1337
  reconnectAttempts++;
1284
1338
  console.log(pc3__default.default.gray(`user streams disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
@@ -1289,6 +1343,7 @@ var connectToUserStreams = async (serverUrl) => {
1289
1343
  }, delay);
1290
1344
  });
1291
1345
  ws.on("error", (error) => {
1346
+ clearHeartbeat();
1292
1347
  console.error(pc3__default.default.red(`stream error: ${error.message}`));
1293
1348
  });
1294
1349
  return ws;
package/dist/server.js CHANGED
@@ -14,7 +14,7 @@ import { z } from 'zod';
14
14
  import { createServer } from 'http';
15
15
  import { batchTool, bashTool, apply_patch, read_file, list, globTool, grepTool, deleteFile, editFiles } from '@ama/agent';
16
16
 
17
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
17
+ var DEFAULT_SERVER_URL = process.env.SERVER_URL || "wss://ama-bridge.shujanshaikh05.workers.dev";
18
18
  var AMA_DIR = path6.join(os3.homedir(), ".amai");
19
19
  path6.join(AMA_DIR, "code");
20
20
  path6.join(AMA_DIR, "storage");
@@ -605,6 +605,7 @@ var Snapshot;
605
605
  })(Snapshot || (Snapshot = {}));
606
606
  var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
607
607
  var ISSUER = "https://auth.openai.com";
608
+ var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
608
609
  var OAUTH_PORT = 1455;
609
610
  var CREDENTIALS_PATH2 = path6.join(AMA_DIR, "codex-credentials.json");
610
611
  var CALLBACK_PATH = "/auth/callback";
@@ -996,6 +997,30 @@ async function getCodexStatus() {
996
997
  return { authenticated: false };
997
998
  }
998
999
  }
1000
+ async function codexFetch(body) {
1001
+ const { accessToken, accountId } = await getCodexTokens();
1002
+ const response = await fetch(CODEX_API_ENDPOINT, {
1003
+ method: "POST",
1004
+ headers: {
1005
+ "Content-Type": "application/json",
1006
+ Authorization: `Bearer ${accessToken}`,
1007
+ "ChatGPT-Account-Id": accountId,
1008
+ originator: "ama",
1009
+ Accept: "text/event-stream"
1010
+ },
1011
+ body
1012
+ });
1013
+ const text = await response.text();
1014
+ const headers = {};
1015
+ response.headers.forEach((value, key) => {
1016
+ headers[key] = value;
1017
+ });
1018
+ return {
1019
+ status: response.status,
1020
+ headers,
1021
+ body: text
1022
+ };
1023
+ }
999
1024
  async function codexLogout() {
1000
1025
  pendingOAuth = void 0;
1001
1026
  stopOAuthServer();
@@ -1162,6 +1187,16 @@ var rpcHandlers = {
1162
1187
  "daemon:codex_get_tokens": async () => {
1163
1188
  return getCodexTokens();
1164
1189
  },
1190
+ "daemon:codex_fetch": async ({ body }) => {
1191
+ if (typeof body !== "string" || !body.trim()) {
1192
+ const error = {
1193
+ _tag: "ValidationError",
1194
+ message: "body is required"
1195
+ };
1196
+ throw error;
1197
+ }
1198
+ return codexFetch(body);
1199
+ },
1165
1200
  "daemon:codex_status": async () => {
1166
1201
  return getCodexStatus();
1167
1202
  },
@@ -1173,8 +1208,10 @@ var rpcHandlers = {
1173
1208
  var INITIAL_RECONNECT_DELAY = 1e3;
1174
1209
  var MAX_RECONNECT_DELAY = 6e4;
1175
1210
  var BACKOFF_MULTIPLIER = 2;
1211
+ var CLI_HEARTBEAT_INTERVAL_MS = 5e3;
1176
1212
  var reconnectTimeout = null;
1177
1213
  var reconnectAttempts = 0;
1214
+ var heartbeatInterval = null;
1178
1215
  function getReconnectDelay() {
1179
1216
  const delay = Math.min(
1180
1217
  INITIAL_RECONNECT_DELAY * Math.pow(BACKOFF_MULTIPLIER, reconnectAttempts),
@@ -1202,6 +1239,19 @@ var connectToUserStreams = async (serverUrl) => {
1202
1239
  Authorization: `Bearer ${tokens.access_token}`
1203
1240
  }
1204
1241
  });
1242
+ const clearHeartbeat = () => {
1243
+ if (heartbeatInterval) {
1244
+ clearInterval(heartbeatInterval);
1245
+ heartbeatInterval = null;
1246
+ }
1247
+ };
1248
+ const sendHeartbeat = () => {
1249
+ if (ws.readyState !== WebSocket2.OPEN) return;
1250
+ ws.send(JSON.stringify({
1251
+ _tag: "cli_heartbeat",
1252
+ timestamp: Date.now()
1253
+ }));
1254
+ };
1205
1255
  ws.on("open", () => {
1206
1256
  reconnectAttempts = 0;
1207
1257
  console.log(pc3.cyan("connected to user streams"));
@@ -1209,6 +1259,9 @@ var connectToUserStreams = async (serverUrl) => {
1209
1259
  clearTimeout(reconnectTimeout);
1210
1260
  reconnectTimeout = null;
1211
1261
  }
1262
+ clearHeartbeat();
1263
+ sendHeartbeat();
1264
+ heartbeatInterval = setInterval(sendHeartbeat, CLI_HEARTBEAT_INTERVAL_MS);
1212
1265
  });
1213
1266
  ws.on("message", async (event) => {
1214
1267
  try {
@@ -1268,6 +1321,7 @@ var connectToUserStreams = async (serverUrl) => {
1268
1321
  }
1269
1322
  });
1270
1323
  ws.on("close", (code, reason) => {
1324
+ clearHeartbeat();
1271
1325
  const delay = getReconnectDelay();
1272
1326
  reconnectAttempts++;
1273
1327
  console.log(pc3.gray(`user streams disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
@@ -1278,6 +1332,7 @@ var connectToUserStreams = async (serverUrl) => {
1278
1332
  }, delay);
1279
1333
  });
1280
1334
  ws.on("error", (error) => {
1335
+ clearHeartbeat();
1281
1336
  console.error(pc3.red(`stream error: ${error.message}`));
1282
1337
  });
1283
1338
  return ws;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "amai",
3
3
  "type": "module",
4
- "version": "0.0.22",
4
+ "version": "0.0.23",
5
5
  "description": "ama cli",
6
6
  "keywords": [
7
7
  "ama",