axexec 1.1.4 → 1.1.6

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.
@@ -11,7 +11,7 @@ import type { ChildProcess } from "node:child_process";
11
11
  * 1. Cancel SSE reader (unblocks pending reads)
12
12
  * 2. Abort session via API (needs server alive)
13
13
  * 3. Dispose server instance via API (needs server alive)
14
- * 4. Kill server process
14
+ * 4. Kill server process and close stdio streams
15
15
  */
16
16
  declare function cleanupSession(serverProcess: ChildProcess | undefined, serverUrl: string | undefined, sessionId: string | undefined, sessionComplete: boolean, sseReader: ReadableStreamDefaultReader<Uint8Array> | undefined, cwd: string): Promise<void>;
17
17
  export { cleanupSession };
@@ -11,7 +11,7 @@ import { abortSession, disposeInstance } from "./session-api.js";
11
11
  * 1. Cancel SSE reader (unblocks pending reads)
12
12
  * 2. Abort session via API (needs server alive)
13
13
  * 3. Dispose server instance via API (needs server alive)
14
- * 4. Kill server process
14
+ * 4. Kill server process and close stdio streams
15
15
  */
16
16
  async function cleanupSession(serverProcess, serverUrl, sessionId, sessionComplete, sseReader, cwd) {
17
17
  // Cancel SSE reader directly to unblock any pending reads
@@ -26,6 +26,10 @@ async function cleanupSession(serverProcess, serverUrl, sessionId, sessionComple
26
26
  // Kill server gracefully with SIGTERM, then force with SIGKILL after timeout
27
27
  if (!serverProcess || serverProcess.killed)
28
28
  return;
29
+ // Destroy stdio streams to prevent them from keeping Node.js alive
30
+ serverProcess.stdout?.destroy();
31
+ serverProcess.stderr?.destroy();
32
+ serverProcess.stdin?.destroy();
29
33
  serverProcess.kill("SIGTERM");
30
34
  // Wait for process to exit (with timeout for SIGKILL escalation)
31
35
  await new Promise((resolve) => {
@@ -42,8 +42,10 @@ async function* processSSEEvents(sseGenerator, context) {
42
42
  });
43
43
  sessionStartEmitted = true;
44
44
  }
45
- if (isSessionIdleEvent(sseEvent))
45
+ if (isSessionIdleEvent(sseEvent)) {
46
46
  sessionComplete = true;
47
+ context.onComplete();
48
+ }
47
49
  const axexecEvents = parseEvent(sseEvent);
48
50
  for (const event of axexecEvents) {
49
51
  trackContentEvent(contentTracker, event);
@@ -52,11 +54,15 @@ async function* processSSEEvents(sseGenerator, context) {
52
54
  if (emptyError) {
53
55
  yield emptyError;
54
56
  context.onAbort();
57
+ // Close SSE generator to trigger its finally block (closes HTTP connection)
58
+ await sseGenerator.return({ sessionStartEmitted, sessionComplete });
55
59
  return { sessionStartEmitted, sessionComplete };
56
60
  }
57
61
  yield event;
58
62
  if (event.type === "session.complete" || event.type === "session.error") {
59
63
  context.onAbort();
64
+ // Close SSE generator to trigger its finally block (closes HTTP connection)
65
+ await sseGenerator.return({ sessionStartEmitted, sessionComplete });
60
66
  return { sessionStartEmitted, sessionComplete };
61
67
  }
62
68
  }
@@ -23,11 +23,11 @@ declare function installClaudeCredentials(configDirectory: string, credentials:
23
23
  * Installs Codex credentials to a config directory.
24
24
  *
25
25
  * File: auth.json
26
- * Format: { OPENAI_API_KEY: "..." } or { tokens: { ... }, last_refresh: "..." }
26
+ * Format: { OPENAI_API_KEY: "..." } or { OPENAI_API_KEY: null, tokens: { id_token, access_token, refresh_token, account_id }, last_refresh: "..." }
27
27
  *
28
28
  * Handles:
29
29
  * - api-key: Written as { OPENAI_API_KEY: "..." }
30
- * - oauth-credentials: Written as { tokens: { ... }, last_refresh: "..." }
30
+ * - oauth-credentials: Written directly (expected to already have correct structure)
31
31
  */
32
32
  declare function installCodexCredentials(configDirectory: string, credentials: Credentials, warn?: WarningWriter): void;
33
33
  /**
@@ -40,11 +40,11 @@ function installClaudeCredentials(configDirectory, credentials) {
40
40
  * Installs Codex credentials to a config directory.
41
41
  *
42
42
  * File: auth.json
43
- * Format: { OPENAI_API_KEY: "..." } or { tokens: { ... }, last_refresh: "..." }
43
+ * Format: { OPENAI_API_KEY: "..." } or { OPENAI_API_KEY: null, tokens: { id_token, access_token, refresh_token, account_id }, last_refresh: "..." }
44
44
  *
45
45
  * Handles:
46
46
  * - api-key: Written as { OPENAI_API_KEY: "..." }
47
- * - oauth-credentials: Written as { tokens: { ... }, last_refresh: "..." }
47
+ * - oauth-credentials: Written directly (expected to already have correct structure)
48
48
  */
49
49
  function installCodexCredentials(configDirectory, credentials, warn = defaultWarningWriter) {
50
50
  const authPath = path.join(configDirectory, "auth.json");
@@ -59,10 +59,12 @@ function installCodexCredentials(configDirectory, credentials, warn = defaultWar
59
59
  break;
60
60
  }
61
61
  case "oauth-credentials": {
62
- saveJsonFile(authPath, {
63
- tokens: credentials.data,
64
- last_refresh: new Date().toISOString(),
65
- });
62
+ // Codex expects { OPENAI_API_KEY, tokens: { id_token, access_token, refresh_token, account_id }, last_refresh }
63
+ // The vault stores credentials in this exact format, so write directly.
64
+ // Remove internal _source field if present.
65
+ const data = { ...credentials.data };
66
+ delete data["_source"];
67
+ saveJsonFile(authPath, data);
66
68
  break;
67
69
  }
68
70
  case "oauth-token": {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "axexec",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "1.1.4",
5
+ "version": "1.1.6",
6
6
  "description": "Unified CLI runner for AI coding agents with normalized event streaming",
7
7
  "repository": {
8
8
  "type": "git",