axexec 1.1.5 → 1.2.0

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.
@@ -9,7 +9,6 @@
9
9
  * to stdout.
10
10
  */
11
11
  import path from "node:path";
12
- import { fileURLToPath } from "node:url";
13
12
  import { determineSessionSuccess } from "../../determine-session-success.js";
14
13
  import { resolveBinary } from "../../resolve-binary.js";
15
14
  import { registerAdapter } from "../registry.js";
@@ -21,7 +20,7 @@ const COPILOT_INFO = {
21
20
  };
22
21
  /** Get the path to the stream-session.js script */
23
22
  function getWrapperScriptPath() {
24
- const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
23
+ const currentDirectory = import.meta.dirname;
25
24
  return path.join(currentDirectory, "stream-session.js");
26
25
  }
27
26
  /**
@@ -87,7 +87,9 @@ async function main() {
87
87
  });
88
88
  });
89
89
  // Give a moment for final events to be written
90
- await new Promise((resolve) => setTimeout(resolve, 200));
90
+ await new Promise((resolve) => {
91
+ setTimeout(resolve, 200);
92
+ });
91
93
  // Stop tailing
92
94
  abortController.abort();
93
95
  // Wait for tail to finish processing
@@ -42,11 +42,15 @@ export async function* tailFile(filePath, signal) {
42
42
  position = fileSize;
43
43
  }
44
44
  // Wait a bit before checking again
45
- await new Promise((resolve) => setTimeout(resolve, 50));
45
+ await new Promise((resolve) => {
46
+ setTimeout(resolve, 50);
47
+ });
46
48
  }
47
49
  catch {
48
50
  // File might be temporarily unavailable, wait and retry
49
- await new Promise((resolve) => setTimeout(resolve, 100));
51
+ await new Promise((resolve) => {
52
+ setTimeout(resolve, 100);
53
+ });
50
54
  }
51
55
  }
52
56
  }
@@ -136,18 +136,20 @@ export function waitForSessionFile(existingFiles, timeoutMs = 10_000) {
136
136
  const eventsFile = path.join(SESSION_STATE_DIR, filename, SESSION_EVENTS_FILE);
137
137
  const checkForEventsFile = () => {
138
138
  if (resolved)
139
- return;
139
+ return true;
140
140
  if (existsSync(eventsFile)) {
141
141
  resolved = true;
142
142
  cleanup();
143
143
  resolve(eventsFile);
144
+ return true;
144
145
  }
146
+ return false;
145
147
  };
146
148
  // Check immediately and set up short polling for the events file
147
- checkForEventsFile();
148
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- resolved may be set by checkForEventsFile
149
- if (!resolved) {
150
- eventsCheckInterval = setInterval(checkForEventsFile, 50);
149
+ if (!checkForEventsFile()) {
150
+ eventsCheckInterval = setInterval(() => {
151
+ checkForEventsFile();
152
+ }, 50);
151
153
  }
152
154
  }
153
155
  });
@@ -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) => {
@@ -2,7 +2,7 @@
2
2
  * SSE event processing for OpenCode adapter.
3
3
  */
4
4
  import type { AxexecEvent } from "../../types/events.js";
5
- import { OpenCodeSSEEvent } from "./server-types.js";
5
+ import type { OpenCodeSSEEvent } from "./server-types.js";
6
6
  interface ProcessEventsContext {
7
7
  serverUrl: string;
8
8
  sessionId: string;
@@ -4,7 +4,7 @@
4
4
  import { createSessionStartEvent } from "./create-session-start-event.js";
5
5
  import { checkEmptySession, createContentTracker, trackContentEvent, } from "./detect-empty-session.js";
6
6
  import { createSSEEventParser } from "./parse-sse-event.js";
7
- import { isMessagePartUpdatedEvent, isSessionErrorEvent, isSessionIdleEvent, OpenCodeSSEEvent, } from "./server-types.js";
7
+ import { isMessagePartUpdatedEvent, isSessionErrorEvent, isSessionIdleEvent, } from "./server-types.js";
8
8
  import { getSessionModelInfo } from "./session-api.js";
9
9
  /**
10
10
  * Processes SSE events and yields normalized AxexecEvents.
@@ -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
  }
@@ -5,7 +5,7 @@
5
5
  * without modifying core code.
6
6
  */
7
7
  import type { AgentAdapter, AgentInfo } from "../types/adapter.js";
8
- import type { AgentCli } from "../types/events.js";
8
+ import type { AgentCli } from "axshared";
9
9
  /** Registers an adapter in the registry */
10
10
  declare function registerAdapter(adapter: AgentAdapter): void;
11
11
  /** Retrieves an adapter by ID, or undefined if not found */
@@ -1,4 +1,4 @@
1
- import type { AgentCli } from "./types/events.js";
1
+ import type { AgentCli } from "axshared";
2
2
  import type { RunAgentOptions, ExecutionMetadata } from "./types/run-result.js";
3
3
  import type { Credentials } from "./credentials/credentials.js";
4
4
  import type { installCredentials } from "./credentials/install-credentials.js";
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Permission config building for agent execution.
3
3
  */
4
- import type { AgentCli } from "./types/events.js";
4
+ import type { AgentCli } from "axshared";
5
5
  import type { RunAgentOptions } from "./types/run-result.js";
6
6
  import type { installCredentials } from "./credentials/install-credentials.js";
7
7
  type CredentialInstallResult = Awaited<ReturnType<typeof installCredentials>>;
package/dist/cli.js CHANGED
@@ -112,6 +112,7 @@ Examples:
112
112
  });
113
113
  // Set exit code based on success
114
114
  if (!result.success) {
115
+ // eslint-disable-next-line require-atomic-updates
115
116
  process.exitCode = 1;
116
117
  }
117
118
  });
@@ -118,6 +118,11 @@ function installOpenCodeCredentials(dataDirectory, credentials, warn = defaultWa
118
118
  });
119
119
  break;
120
120
  }
121
+ case "oauth-token": {
122
+ // OpenCode doesn't support oauth-token, only oauth-credentials
123
+ warn(`Warning: installOpenCodeCredentials: oauth-token is not supported for OpenCode. auth.json was not written.`);
124
+ break;
125
+ }
121
126
  case "api-key": {
122
127
  const apiKey = resolveStringField(credentials.data, "apiKey", "key");
123
128
  if (!apiKey) {
@@ -1,5 +1,5 @@
1
1
  import type { AgentAdapter } from "./types/adapter.js";
2
- import type { AgentCli } from "./types/events.js";
2
+ import type { AgentCli } from "axshared";
3
3
  import type { RunAgentOptions, RunResult } from "./types/run-result.js";
4
4
  import type { Credentials } from "./credentials/credentials.js";
5
5
  import type { installCredentials } from "./credentials/install-credentials.js";
package/dist/index.d.ts CHANGED
@@ -12,5 +12,5 @@ import "./agents/copilot/adapter.js";
12
12
  export { runAgent } from "./run-agent.js";
13
13
  export { cleanupCredentials } from "./credentials/install-credentials.js";
14
14
  export type { ExecutionCredentials, ExecutionDirectories, ExecutionMetadata, RunAgentDiagnostics, RunAgentOptions, RunResult, } from "./types/run-result.js";
15
- export type { AxexecEvent, AgentCli } from "./types/events.js";
15
+ export type { AxexecEvent } from "./types/events.js";
16
16
  export type { Credentials } from "./credentials/credentials.js";
@@ -7,7 +7,8 @@
7
7
  * Adapters may optionally implement {@link StreamableAdapter} to provide
8
8
  * custom streaming behavior (e.g., for server-mode agents).
9
9
  */
10
- import type { AgentCli, AxexecEvent } from "./events.js";
10
+ import type { AgentCli } from "axshared";
11
+ import type { AxexecEvent } from "./events.js";
11
12
  import type { RunOptions } from "./options.js";
12
13
  /** Metadata about an agent */
13
14
  interface AgentInfo {
@@ -10,8 +10,7 @@
10
10
  * - agent.*: Agent content output (reasoning, message)
11
11
  * - tool.*: Tool execution (call, result)
12
12
  */
13
- export type { AgentCli } from "axshared";
14
- type AgentCli = import("axshared").AgentCli;
13
+ import type { AgentCli } from "axshared";
15
14
  /** Statistics collected during session execution */
16
15
  interface SessionStats {
17
16
  durationMs: number;
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Types for run-agent results and options.
3
3
  */
4
- import type { AgentCli, AxexecEvent } from "./events.js";
4
+ import type { AgentCli } from "axshared";
5
+ import type { AxexecEvent } from "./events.js";
5
6
  import type { OutputFormat } from "../resolve-output-mode.js";
6
7
  import type { Credentials } from "../credentials/credentials.js";
7
8
  interface RunAgentDiagnostics {
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.5",
5
+ "version": "1.2.0",
6
6
  "description": "Unified CLI runner for AI coding agents with normalized event streaming",
7
7
  "repository": {
8
8
  "type": "git",
@@ -75,7 +75,7 @@
75
75
  "@types/node": "^25.0.7",
76
76
  "@vitest/coverage-v8": "^4.0.17",
77
77
  "eslint": "^9.39.2",
78
- "eslint-config-axkit": "^1.0.0",
78
+ "eslint-config-axkit": "^1.1.0",
79
79
  "fta-check": "^1.5.1",
80
80
  "fta-cli": "^3.0.0",
81
81
  "knip": "^5.80.2",