@northflare/runner 0.0.26 → 0.0.27

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.
Files changed (37) hide show
  1. package/dist/components/claude-sdk-manager.d.ts.map +1 -1
  2. package/dist/components/claude-sdk-manager.js +9 -1
  3. package/dist/components/claude-sdk-manager.js.map +1 -1
  4. package/dist/components/codex-sdk-manager.d.ts.map +1 -1
  5. package/dist/components/codex-sdk-manager.js +8 -0
  6. package/dist/components/codex-sdk-manager.js.map +1 -1
  7. package/dist/components/message-handler-sse.d.ts.map +1 -1
  8. package/dist/components/message-handler-sse.js +10 -2
  9. package/dist/components/message-handler-sse.js.map +1 -1
  10. package/dist/components/northflare-agent-sdk-manager.d.ts.map +1 -1
  11. package/dist/components/northflare-agent-sdk-manager.js +16 -3
  12. package/dist/components/northflare-agent-sdk-manager.js.map +1 -1
  13. package/dist/runner-sse.d.ts +16 -0
  14. package/dist/runner-sse.d.ts.map +1 -1
  15. package/dist/runner-sse.js +55 -7
  16. package/dist/runner-sse.js.map +1 -1
  17. package/dist/services/SSEClient.d.ts +2 -0
  18. package/dist/services/SSEClient.d.ts.map +1 -1
  19. package/dist/services/SSEClient.js +4 -1
  20. package/dist/services/SSEClient.js.map +1 -1
  21. package/dist/types/messages.d.ts +2 -0
  22. package/dist/types/messages.d.ts.map +1 -1
  23. package/dist/types/runner-interface.d.ts +3 -0
  24. package/dist/types/runner-interface.d.ts.map +1 -1
  25. package/dist/utils/StateManager.d.ts +10 -1
  26. package/dist/utils/StateManager.d.ts.map +1 -1
  27. package/dist/utils/StateManager.js +38 -23
  28. package/dist/utils/StateManager.js.map +1 -1
  29. package/dist/utils/update-coordinator.d.ts +53 -0
  30. package/dist/utils/update-coordinator.d.ts.map +1 -0
  31. package/dist/utils/update-coordinator.js +159 -0
  32. package/dist/utils/update-coordinator.js.map +1 -0
  33. package/dist/utils/version.d.ts +10 -0
  34. package/dist/utils/version.d.ts.map +1 -0
  35. package/dist/utils/version.js +33 -0
  36. package/dist/utils/version.js.map +1 -0
  37. package/package.json +4 -4
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Coordinates runner auto-updates.
3
+ *
4
+ * When the server sends an expectedRunnerVersion that is newer than the current
5
+ * version, the coordinator notes the pending update and waits for the runner to
6
+ * become idle (no active conversations) before executing the update.
7
+ *
8
+ * The update is performed by spawning a new process with npx, which ensures
9
+ * the latest version is fetched and executed with the same arguments/env.
10
+ */
11
+ import { spawn } from "child_process";
12
+ import { logger } from "./logger.js";
13
+ import { RUNNER_VERSION, isNewerVersion } from "./version.js";
14
+ export class UpdateCoordinator {
15
+ state = "idle";
16
+ pendingVersion = null;
17
+ options;
18
+ constructor(options) {
19
+ this.options = options;
20
+ }
21
+ get currentState() {
22
+ return this.state;
23
+ }
24
+ get hasPendingUpdate() {
25
+ return this.state === "pending";
26
+ }
27
+ get pendingVersionNumber() {
28
+ return this.pendingVersion;
29
+ }
30
+ /**
31
+ * Called when a message is received with an expectedRunnerVersion.
32
+ * If the version is newer, marks an update as pending.
33
+ * If the runner is already idle, triggers the update immediately.
34
+ *
35
+ * @returns true if an update was triggered or marked as pending
36
+ */
37
+ async checkVersion(serverVersion) {
38
+ if (this.options.autoUpdateDisabled) {
39
+ logger.debug("Auto-update disabled via NORTHFLARE_DISABLE_AUTO_UPDATE");
40
+ return false;
41
+ }
42
+ // Already handling an update
43
+ if (this.state !== "idle" && this.state !== "pending") {
44
+ logger.debug("Update already in progress", { state: this.state });
45
+ return false;
46
+ }
47
+ // Check if server version is newer
48
+ if (!isNewerVersion(serverVersion, RUNNER_VERSION)) {
49
+ return false;
50
+ }
51
+ // Already have this version pending
52
+ if (this.pendingVersion === serverVersion) {
53
+ return false;
54
+ }
55
+ // Mark update as pending
56
+ this.pendingVersion = serverVersion;
57
+ this.state = "pending";
58
+ logger.info(`Update available: ${serverVersion} (current: ${RUNNER_VERSION}). ` +
59
+ `Will update when idle.`);
60
+ // If already idle, update now
61
+ if (this.options.getActiveConversationCount() === 0) {
62
+ await this.executeUpdate();
63
+ return true;
64
+ }
65
+ logger.info(`${this.options.getActiveConversationCount()} active conversation(s). ` +
66
+ `Update will proceed when all complete.`);
67
+ return true;
68
+ }
69
+ /**
70
+ * Called when a conversation ends. If there's a pending update and the
71
+ * runner is now idle, triggers the update.
72
+ */
73
+ async onConversationEnd() {
74
+ if (this.state !== "pending" || !this.pendingVersion) {
75
+ return;
76
+ }
77
+ const activeCount = this.options.getActiveConversationCount();
78
+ if (activeCount > 0) {
79
+ logger.debug(`Conversation ended, but ${activeCount} still active. ` +
80
+ `Waiting for idle before update.`);
81
+ return;
82
+ }
83
+ logger.info("Runner now idle, proceeding with pending update");
84
+ await this.executeUpdate();
85
+ }
86
+ /**
87
+ * Executes the update by spawning a new runner process and exiting.
88
+ */
89
+ async executeUpdate() {
90
+ if (!this.pendingVersion) {
91
+ logger.error("executeUpdate called but no pending version");
92
+ return;
93
+ }
94
+ this.state = "updating";
95
+ logger.info(`Installing @northflare/runner@${this.pendingVersion}...`);
96
+ try {
97
+ // Save state before restart so we don't lose lastProcessedAt, etc.
98
+ await this.options.saveState();
99
+ logger.debug("State saved before update");
100
+ }
101
+ catch (error) {
102
+ logger.error("Failed to save state before update:", error);
103
+ // Continue anyway - better to update than to stay on old version
104
+ }
105
+ // Build the npx command
106
+ // Using -y to auto-confirm and specifying the exact version
107
+ const npxCommand = "npx";
108
+ const npxArgs = [
109
+ "-y",
110
+ `@northflare/runner@${this.pendingVersion}`,
111
+ ...this.buildRestartArgs(),
112
+ ];
113
+ logger.info(`Restarting with: ${npxCommand} ${npxArgs.join(" ")}`);
114
+ this.state = "restarting";
115
+ // Spawn new process detached so it survives our exit
116
+ const child = spawn(npxCommand, npxArgs, {
117
+ detached: true,
118
+ stdio: "inherit",
119
+ env: process.env,
120
+ shell: true,
121
+ });
122
+ // Prevent parent from waiting for child
123
+ child.unref();
124
+ // Handle spawn errors
125
+ child.on("error", (error) => {
126
+ logger.error("Failed to spawn update process:", error);
127
+ // Reset state so we can try again
128
+ this.state = "pending";
129
+ });
130
+ // Give the new process a moment to start before we exit
131
+ await new Promise((resolve) => setTimeout(resolve, 1000));
132
+ // Exit current process
133
+ logger.info("Exiting for update...");
134
+ process.exit(0);
135
+ }
136
+ /**
137
+ * Builds the command-line arguments for the restarted runner.
138
+ * Most config is passed via environment variables which are inherited.
139
+ */
140
+ buildRestartArgs() {
141
+ const args = [];
142
+ // Add start command explicitly
143
+ args.push("start");
144
+ // Config path if provided
145
+ const configPath = this.options.getConfigPath();
146
+ if (configPath) {
147
+ args.push("--config", configPath);
148
+ }
149
+ // Other options are passed via inherited env vars:
150
+ // - NORTHFLARE_RUNNER_TOKEN
151
+ // - NORTHFLARE_WORKSPACE_PATH
152
+ // - NORTHFLARE_DATA_DIR
153
+ // - NORTHFLARE_RUNNER_DEBUG
154
+ // - NORTHFLARE_RUNNER_INACTIVITY_TIMEOUT
155
+ // - NORTHFLARE_ORCHESTRATOR_URL
156
+ return args;
157
+ }
158
+ }
159
+ //# sourceMappingURL=update-coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-coordinator.js","sourceRoot":"","sources":["../../src/utils/update-coordinator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Version utilities for runner auto-update
3
+ */
4
+ export declare const RUNNER_VERSION: string;
5
+ /**
6
+ * Compare two semver versions.
7
+ * Returns true if serverVersion is newer than currentVersion.
8
+ */
9
+ export declare function isNewerVersion(serverVersion: string, currentVersion: string): boolean;
10
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,eAAO,MAAM,cAAc,EAAE,MAAoB,CAAC;AAElD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAoBrF"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Version utilities for runner auto-update
3
+ */
4
+ import { createRequire } from "module";
5
+ const require = createRequire(import.meta.url);
6
+ const pkg = require("../../package.json");
7
+ export const RUNNER_VERSION = pkg.version;
8
+ /**
9
+ * Compare two semver versions.
10
+ * Returns true if serverVersion is newer than currentVersion.
11
+ */
12
+ export function isNewerVersion(serverVersion, currentVersion) {
13
+ const parse = (v) => {
14
+ // Handle versions like "0.0.26" or "1.2.3-beta.1"
15
+ const match = v.match(/^(\d+)\.(\d+)\.(\d+)/);
16
+ if (!match) {
17
+ return [0, 0, 0];
18
+ }
19
+ return [
20
+ parseInt(match[1], 10),
21
+ parseInt(match[2], 10),
22
+ parseInt(match[3], 10),
23
+ ];
24
+ };
25
+ const [sMajor, sMinor, sPatch] = parse(serverVersion);
26
+ const [cMajor, cMinor, cPatch] = parse(currentVersion);
27
+ if (sMajor !== cMajor)
28
+ return sMajor > cMajor;
29
+ if (sMinor !== cMinor)
30
+ return sMinor > cMinor;
31
+ return sPatch > cPatch;
32
+ }
33
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAE1C,MAAM,CAAC,MAAM,cAAc,GAAW,GAAG,CAAC,OAAO,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,aAAqB,EAAE,cAAsB;IAC1E,MAAM,KAAK,GAAG,CAAC,CAAS,EAA4B,EAAE;QACpD,kDAAkD;QAClD,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC;QACD,OAAO;YACL,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;YACvB,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;YACvB,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;SACxB,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC;IACtD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IAEvD,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,GAAG,MAAM,CAAC;IAC9C,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,GAAG,MAAM,CAAC;IAC9C,OAAO,MAAM,GAAG,MAAM,CAAC;AACzB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@northflare/runner",
3
- "version": "0.0.26",
3
+ "version": "0.0.27",
4
4
  "description": "Distributed conversation runner for Northflare",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,7 +12,7 @@
12
12
  "@anthropic-ai/claude-agent-sdk": "0.1.51",
13
13
  "@botanicastudios/claude-code-sdk-ts": "0.2.22-fork",
14
14
  "@botanicastudios/mcp-host-rpc": "^0.4.0",
15
- "@openai/codex-sdk": "^0.71.0",
15
+ "@openai/codex-sdk": "^0.77.0",
16
16
  "@openrouter/ai-sdk-provider": "^1.2.8",
17
17
  "@tanstack/react-query": "^5.x.x",
18
18
  "@types/jsonwebtoken": "^9.0.10",
@@ -27,8 +27,8 @@
27
27
  "simple-git": "^3.x.x",
28
28
  "winston": "^3.x.x",
29
29
  "zod": "^3.25.8",
30
- "@northflare/codex-sdk": "0.1.0",
31
- "@northflare/agent": "0.1.3"
30
+ "@northflare/agent": "0.1.3",
31
+ "@northflare/codex-sdk": "0.1.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/eventsource": "^1.1.15",