@northflare/runner 0.0.8 → 0.0.10

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 (101) hide show
  1. package/dist/components/claude-sdk-manager.d.ts +1 -1
  2. package/dist/components/claude-sdk-manager.d.ts.map +1 -1
  3. package/dist/components/claude-sdk-manager.js +30 -16
  4. package/dist/components/claude-sdk-manager.js.map +1 -1
  5. package/dist/components/codex-sdk-manager.d.ts +60 -0
  6. package/dist/components/codex-sdk-manager.d.ts.map +1 -0
  7. package/dist/components/codex-sdk-manager.js +988 -0
  8. package/dist/components/codex-sdk-manager.js.map +1 -0
  9. package/dist/components/message-handler-sse.d.ts +3 -0
  10. package/dist/components/message-handler-sse.d.ts.map +1 -1
  11. package/dist/components/message-handler-sse.js +66 -21
  12. package/dist/components/message-handler-sse.js.map +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +4 -2
  15. package/dist/index.js.map +1 -1
  16. package/dist/runner-sse.d.ts +4 -0
  17. package/dist/runner-sse.d.ts.map +1 -1
  18. package/dist/runner-sse.js +63 -20
  19. package/dist/runner-sse.js.map +1 -1
  20. package/dist/runner.js +3 -3
  21. package/dist/types/claude.d.ts +11 -1
  22. package/dist/types/claude.d.ts.map +1 -1
  23. package/dist/types/index.d.ts +1 -0
  24. package/dist/types/index.d.ts.map +1 -1
  25. package/dist/types/runner-interface.d.ts +2 -0
  26. package/dist/types/runner-interface.d.ts.map +1 -1
  27. package/dist/utils/config.d.ts.map +1 -1
  28. package/dist/utils/config.js +1 -0
  29. package/dist/utils/config.js.map +1 -1
  30. package/dist/utils/console.d.ts.map +1 -1
  31. package/dist/utils/console.js +2 -1
  32. package/dist/utils/console.js.map +1 -1
  33. package/dist/utils/debug.d.ts +2 -0
  34. package/dist/utils/debug.d.ts.map +1 -0
  35. package/dist/utils/debug.js +19 -0
  36. package/dist/utils/debug.js.map +1 -0
  37. package/dist/utils/logger.d.ts.map +1 -1
  38. package/dist/utils/logger.js +6 -4
  39. package/dist/utils/logger.js.map +1 -1
  40. package/dist/utils/model.d.ts +6 -0
  41. package/dist/utils/model.d.ts.map +1 -0
  42. package/dist/utils/model.js +23 -0
  43. package/dist/utils/model.js.map +1 -0
  44. package/dist/utils/status-line.d.ts +0 -8
  45. package/dist/utils/status-line.d.ts.map +1 -1
  46. package/dist/utils/status-line.js +9 -8
  47. package/dist/utils/status-line.js.map +1 -1
  48. package/dist/utils/tool-response-sanitizer.d.ts +9 -0
  49. package/dist/utils/tool-response-sanitizer.d.ts.map +1 -0
  50. package/dist/utils/tool-response-sanitizer.js +122 -0
  51. package/dist/utils/tool-response-sanitizer.js.map +1 -0
  52. package/exceptions.log +2 -0
  53. package/lib/codex-sdk/.prettierignore +3 -0
  54. package/lib/codex-sdk/.prettierrc +5 -0
  55. package/lib/codex-sdk/README.md +133 -0
  56. package/lib/codex-sdk/dist/index.d.ts +260 -0
  57. package/lib/codex-sdk/dist/index.js +426 -0
  58. package/lib/codex-sdk/eslint.config.js +21 -0
  59. package/lib/codex-sdk/jest.config.cjs +31 -0
  60. package/lib/codex-sdk/package.json +65 -0
  61. package/lib/codex-sdk/samples/basic_streaming.ts +90 -0
  62. package/lib/codex-sdk/samples/helpers.ts +8 -0
  63. package/lib/codex-sdk/samples/structured_output.ts +22 -0
  64. package/lib/codex-sdk/samples/structured_output_zod.ts +19 -0
  65. package/lib/codex-sdk/src/codex.ts +38 -0
  66. package/lib/codex-sdk/src/codexOptions.ts +10 -0
  67. package/lib/codex-sdk/src/events.ts +80 -0
  68. package/lib/codex-sdk/src/exec.ts +336 -0
  69. package/lib/codex-sdk/src/index.ts +39 -0
  70. package/lib/codex-sdk/src/items.ts +127 -0
  71. package/lib/codex-sdk/src/outputSchemaFile.ts +40 -0
  72. package/lib/codex-sdk/src/thread.ts +155 -0
  73. package/lib/codex-sdk/src/threadOptions.ts +18 -0
  74. package/lib/codex-sdk/src/turnOptions.ts +6 -0
  75. package/lib/codex-sdk/tests/abort.test.ts +165 -0
  76. package/lib/codex-sdk/tests/codexExecSpy.ts +37 -0
  77. package/lib/codex-sdk/tests/responsesProxy.ts +225 -0
  78. package/lib/codex-sdk/tests/run.test.ts +687 -0
  79. package/lib/codex-sdk/tests/runStreamed.test.ts +211 -0
  80. package/lib/codex-sdk/tsconfig.json +24 -0
  81. package/lib/codex-sdk/tsup.config.ts +12 -0
  82. package/package.json +3 -1
  83. package/rejections.log +5 -0
  84. package/src/components/claude-sdk-manager.ts +38 -17
  85. package/src/components/codex-sdk-manager.ts +1349 -0
  86. package/src/components/message-handler-sse.ts +94 -22
  87. package/src/index.ts +4 -2
  88. package/src/runner-sse.ts +75 -20
  89. package/src/types/claude.ts +12 -1
  90. package/src/types/index.ts +1 -0
  91. package/src/types/runner-interface.ts +3 -1
  92. package/src/utils/config.ts +1 -0
  93. package/src/utils/console.ts +4 -2
  94. package/src/utils/debug.ts +18 -0
  95. package/src/utils/logger.ts +8 -5
  96. package/src/utils/model.ts +29 -0
  97. package/src/utils/status-line.ts +9 -8
  98. package/src/utils/tool-response-sanitizer.ts +160 -0
  99. package/tests/tool-response-sanitizer.test.ts +63 -0
  100. package/src/utils/codex-sdk.js +0 -448
  101. package/src/utils/sdk-demo.js +0 -34
@@ -0,0 +1,211 @@
1
+ import path from "node:path";
2
+
3
+ import { describe, expect, it } from "@jest/globals";
4
+
5
+ import { Codex } from "../src/codex";
6
+ import { ThreadEvent } from "../src/index";
7
+
8
+ import {
9
+ assistantMessage,
10
+ responseCompleted,
11
+ responseStarted,
12
+ sse,
13
+ startResponsesTestProxy,
14
+ } from "./responsesProxy";
15
+
16
+ const codexExecPath = path.join(process.cwd(), "..", "..", "codex-rs", "target", "debug", "codex");
17
+
18
+ describe("Codex", () => {
19
+ it("returns thread events", async () => {
20
+ const { url, close } = await startResponsesTestProxy({
21
+ statusCode: 200,
22
+ responseBodies: [sse(responseStarted(), assistantMessage("Hi!"), responseCompleted())],
23
+ });
24
+
25
+ try {
26
+ const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
27
+
28
+ const thread = client.startThread();
29
+ const result = await thread.runStreamed("Hello, world!");
30
+
31
+ const events: ThreadEvent[] = [];
32
+ for await (const event of result.events) {
33
+ events.push(event);
34
+ }
35
+
36
+ expect(events).toEqual([
37
+ {
38
+ type: "thread.started",
39
+ thread_id: expect.any(String),
40
+ },
41
+ {
42
+ type: "turn.started",
43
+ },
44
+ {
45
+ type: "item.completed",
46
+ item: {
47
+ id: "item_0",
48
+ type: "agent_message",
49
+ text: "Hi!",
50
+ },
51
+ },
52
+ {
53
+ type: "turn.completed",
54
+ usage: {
55
+ cached_input_tokens: 12,
56
+ input_tokens: 42,
57
+ output_tokens: 5,
58
+ },
59
+ },
60
+ ]);
61
+ expect(thread.id).toEqual(expect.any(String));
62
+ } finally {
63
+ await close();
64
+ }
65
+ });
66
+
67
+ it("sends previous items when runStreamed is called twice", async () => {
68
+ const { url, close, requests } = await startResponsesTestProxy({
69
+ statusCode: 200,
70
+ responseBodies: [
71
+ sse(
72
+ responseStarted("response_1"),
73
+ assistantMessage("First response", "item_1"),
74
+ responseCompleted("response_1"),
75
+ ),
76
+ sse(
77
+ responseStarted("response_2"),
78
+ assistantMessage("Second response", "item_2"),
79
+ responseCompleted("response_2"),
80
+ ),
81
+ ],
82
+ });
83
+
84
+ try {
85
+ const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
86
+
87
+ const thread = client.startThread();
88
+ const first = await thread.runStreamed("first input");
89
+ await drainEvents(first.events);
90
+
91
+ const second = await thread.runStreamed("second input");
92
+ await drainEvents(second.events);
93
+
94
+ // Check second request continues the same thread
95
+ expect(requests.length).toBeGreaterThanOrEqual(2);
96
+ const secondRequest = requests[1];
97
+ expect(secondRequest).toBeDefined();
98
+ const payload = secondRequest!.json;
99
+
100
+ const assistantEntry = payload.input.find(
101
+ (entry: { role: string }) => entry.role === "assistant",
102
+ );
103
+ expect(assistantEntry).toBeDefined();
104
+ const assistantText = assistantEntry?.content?.find(
105
+ (item: { type: string; text: string }) => item.type === "output_text",
106
+ )?.text;
107
+ expect(assistantText).toBe("First response");
108
+ } finally {
109
+ await close();
110
+ }
111
+ });
112
+
113
+ it("resumes thread by id when streaming", async () => {
114
+ const { url, close, requests } = await startResponsesTestProxy({
115
+ statusCode: 200,
116
+ responseBodies: [
117
+ sse(
118
+ responseStarted("response_1"),
119
+ assistantMessage("First response", "item_1"),
120
+ responseCompleted("response_1"),
121
+ ),
122
+ sse(
123
+ responseStarted("response_2"),
124
+ assistantMessage("Second response", "item_2"),
125
+ responseCompleted("response_2"),
126
+ ),
127
+ ],
128
+ });
129
+
130
+ try {
131
+ const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
132
+
133
+ const originalThread = client.startThread();
134
+ const first = await originalThread.runStreamed("first input");
135
+ await drainEvents(first.events);
136
+
137
+ const resumedThread = client.resumeThread(originalThread.id!);
138
+ const second = await resumedThread.runStreamed("second input");
139
+ await drainEvents(second.events);
140
+
141
+ expect(resumedThread.id).toBe(originalThread.id);
142
+
143
+ expect(requests.length).toBeGreaterThanOrEqual(2);
144
+ const secondRequest = requests[1];
145
+ expect(secondRequest).toBeDefined();
146
+ const payload = secondRequest!.json;
147
+
148
+ const assistantEntry = payload.input.find(
149
+ (entry: { role: string }) => entry.role === "assistant",
150
+ );
151
+ expect(assistantEntry).toBeDefined();
152
+ const assistantText = assistantEntry?.content?.find(
153
+ (item: { type: string; text: string }) => item.type === "output_text",
154
+ )?.text;
155
+ expect(assistantText).toBe("First response");
156
+ } finally {
157
+ await close();
158
+ }
159
+ });
160
+
161
+ it("applies output schema turn options when streaming", async () => {
162
+ const { url, close, requests } = await startResponsesTestProxy({
163
+ statusCode: 200,
164
+ responseBodies: [
165
+ sse(
166
+ responseStarted("response_1"),
167
+ assistantMessage("Structured response", "item_1"),
168
+ responseCompleted("response_1"),
169
+ ),
170
+ ],
171
+ });
172
+
173
+ const schema = {
174
+ type: "object",
175
+ properties: {
176
+ answer: { type: "string" },
177
+ },
178
+ required: ["answer"],
179
+ additionalProperties: false,
180
+ } as const;
181
+
182
+ try {
183
+ const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
184
+
185
+ const thread = client.startThread();
186
+ const streamed = await thread.runStreamed("structured", { outputSchema: schema });
187
+ await drainEvents(streamed.events);
188
+
189
+ expect(requests.length).toBeGreaterThanOrEqual(1);
190
+ const payload = requests[0];
191
+ expect(payload).toBeDefined();
192
+ const text = payload!.json.text;
193
+ expect(text).toBeDefined();
194
+ expect(text?.format).toEqual({
195
+ name: "codex_output_schema",
196
+ type: "json_schema",
197
+ strict: true,
198
+ schema,
199
+ });
200
+ } finally {
201
+ await close();
202
+ }
203
+ });
204
+ });
205
+
206
+ async function drainEvents(events: AsyncGenerator<ThreadEvent>): Promise<void> {
207
+ let done = false;
208
+ do {
209
+ done = (await events.next()).done ?? false;
210
+ } while (!done);
211
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "allowSyntheticDefaultImports": true,
7
+ "esModuleInterop": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "skipLibCheck": true,
10
+ "strict": true,
11
+ "noUncheckedIndexedAccess": true,
12
+ "resolveJsonModule": true,
13
+ "lib": ["ES2022"],
14
+ "types": ["node", "jest"],
15
+ "sourceMap": true,
16
+ "declaration": true,
17
+ "declarationMap": true,
18
+ "noImplicitAny": true,
19
+ "outDir": "dist",
20
+ "stripInternal": true
21
+ },
22
+ "include": ["src", "tests", "tsup.config.ts", "samples"],
23
+ "exclude": ["dist", "node_modules"]
24
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ format: ["esm"],
6
+ dts: true,
7
+ sourcemap: true,
8
+ clean: true,
9
+ minify: false,
10
+ target: "node18",
11
+ shims: false,
12
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@northflare/runner",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Distributed conversation runner for Northflare",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -24,6 +24,8 @@
24
24
  "@anthropic-ai/claude-agent-sdk": "0.1.37",
25
25
  "@botanicastudios/claude-code-sdk-ts": "0.2.22-fork",
26
26
  "@botanicastudios/mcp-host-rpc": "^0.4.0",
27
+ "@northflare/codex-sdk": "file:lib/codex-sdk",
28
+ "@openai/codex-sdk": "^0.58.0",
27
29
  "@tanstack/react-query": "^5.x.x",
28
30
  "@types/jsonwebtoken": "^9.0.10",
29
31
  "ajv": "^8.x.x",
package/rejections.log CHANGED
@@ -61,3 +61,8 @@
61
61
  {"date":"Mon Sep 08 2025 22:57:44 GMT+0200 (Central European Summer Time)","error":{},"level":"error","message":"unhandledRejection: HTTP 502: \nError: HTTP 502: \n at RunnerApp.sendToOrchestrator (/Users/toby/Code/claudette/runner/dist/runner-sse.js:202:23)\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async RunnerApp.sendToOrchestratorWithRetry (/Users/toby/Code/claudette/runner/dist/runner-sse.js:447:24)\n at async RunnerApp.notify (/Users/toby/Code/claudette/runner/dist/runner-sse.js:157:13)\n at async /Users/toby/Code/claudette/runner/dist/components/claude-manager.js:253:13","os":{"loadavg":[3.6865234375,4.97021484375,5.3193359375],"uptime":194745},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/claudette-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":791696,"external":4349826,"heapTotal":23592960,"heapUsed":17737264,"rss":77004800},"pid":70062,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"Error: HTTP 502: \n at RunnerApp.sendToOrchestrator (/Users/toby/Code/claudette/runner/dist/runner-sse.js:202:23)\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async RunnerApp.sendToOrchestratorWithRetry (/Users/toby/Code/claudette/runner/dist/runner-sse.js:447:24)\n at async RunnerApp.notify (/Users/toby/Code/claudette/runner/dist/runner-sse.js:157:13)\n at async /Users/toby/Code/claudette/runner/dist/components/claude-manager.js:253:13","trace":[{"column":23,"file":"/Users/toby/Code/claudette/runner/dist/runner-sse.js","function":"RunnerApp.sendToOrchestrator","line":202,"method":"sendToOrchestrator","native":false},{"column":5,"file":"node:internal/process/task_queues","function":"process.processTicksAndRejections","line":105,"method":"processTicksAndRejections","native":false},{"column":24,"file":"/Users/toby/Code/claudette/runner/dist/runner-sse.js","function":"async RunnerApp.sendToOrchestratorWithRetry","line":447,"method":"sendToOrchestratorWithRetry","native":false},{"column":13,"file":"/Users/toby/Code/claudette/runner/dist/runner-sse.js","function":"async RunnerApp.notify","line":157,"method":"notify","native":false},{"column":13,"file":"async /Users/toby/Code/claudette/runner/dist/components/claude-manager.js","function":null,"line":253,"method":null,"native":false}]}
62
62
  {"date":"Tue Sep 09 2025 10:29:32 GMT+0200 (Central European Summer Time)","error":{},"level":"error","message":"unhandledRejection: HTTP 502: \nError: HTTP 502: \n at RunnerApp.sendToOrchestrator (/Users/toby/Code/claudette/runner/dist/runner-sse.js:202:23)\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async RunnerApp.sendToOrchestratorWithRetry (/Users/toby/Code/claudette/runner/dist/runner-sse.js:447:24)\n at async RunnerApp.notify (/Users/toby/Code/claudette/runner/dist/runner-sse.js:157:13)\n at async /Users/toby/Code/claudette/runner/dist/components/claude-manager.js:253:13","os":{"loadavg":[3.1787109375,4.40380859375,4.64892578125],"uptime":236253},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/claudette-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":167387,"external":3725517,"heapTotal":25362432,"heapUsed":16211304,"rss":59359232},"pid":7619,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"Error: HTTP 502: \n at RunnerApp.sendToOrchestrator (/Users/toby/Code/claudette/runner/dist/runner-sse.js:202:23)\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async RunnerApp.sendToOrchestratorWithRetry (/Users/toby/Code/claudette/runner/dist/runner-sse.js:447:24)\n at async RunnerApp.notify (/Users/toby/Code/claudette/runner/dist/runner-sse.js:157:13)\n at async /Users/toby/Code/claudette/runner/dist/components/claude-manager.js:253:13","trace":[{"column":23,"file":"/Users/toby/Code/claudette/runner/dist/runner-sse.js","function":"RunnerApp.sendToOrchestrator","line":202,"method":"sendToOrchestrator","native":false},{"column":5,"file":"node:internal/process/task_queues","function":"process.processTicksAndRejections","line":105,"method":"processTicksAndRejections","native":false},{"column":24,"file":"/Users/toby/Code/claudette/runner/dist/runner-sse.js","function":"async RunnerApp.sendToOrchestratorWithRetry","line":447,"method":"sendToOrchestratorWithRetry","native":false},{"column":13,"file":"/Users/toby/Code/claudette/runner/dist/runner-sse.js","function":"async RunnerApp.notify","line":157,"method":"notify","native":false},{"column":13,"file":"async /Users/toby/Code/claudette/runner/dist/components/claude-manager.js","function":null,"line":253,"method":null,"native":false}]}
63
63
  {"date":"Fri Oct 31 2025 15:15:47 GMT+0100 (Central European Standard Time)","error":{"code":"MODULE_NOT_FOUND","path":"/Users/toby/Code/claudette/runner/node_modules/@anthropic-ai/claude-code/package.json","requestPath":"@anthropic-ai/claude-code"},"level":"error","message":"unhandledRejection: Cannot find module '/Users/toby/Code/claudette/runner/node_modules/@anthropic-ai/claude-code/sdk.mjs'. Please verify that the package.json has a valid \"main\" entry\nError: Cannot find module '/Users/toby/Code/claudette/runner/node_modules/@anthropic-ai/claude-code/sdk.mjs'. Please verify that the package.json has a valid \"main\" entry\n at tryPackage (node:internal/modules/cjs/loader:511:19)\n at Function._findPath (node:internal/modules/cjs/loader:796:18)\n at Function._resolveFilename (node:internal/modules/cjs/loader:1387:27)\n at defaultResolveImpl (node:internal/modules/cjs/loader:1057:19)\n at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1062:22)\n at Function._load (node:internal/modules/cjs/loader:1211:37)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","os":{"loadavg":[10.09228515625,5.86376953125,4.3662109375],"uptime":187703},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/claudette-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":12531,"external":1652665,"heapTotal":10829824,"heapUsed":7045984,"rss":56049664},"pid":4552,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"Error: Cannot find module '/Users/toby/Code/claudette/runner/node_modules/@anthropic-ai/claude-code/sdk.mjs'. Please verify that the package.json has a valid \"main\" entry\n at tryPackage (node:internal/modules/cjs/loader:511:19)\n at Function._findPath (node:internal/modules/cjs/loader:796:18)\n at Function._resolveFilename (node:internal/modules/cjs/loader:1387:27)\n at defaultResolveImpl (node:internal/modules/cjs/loader:1057:19)\n at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1062:22)\n at Function._load (node:internal/modules/cjs/loader:1211:37)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","trace":[{"column":19,"file":"node:internal/modules/cjs/loader","function":"tryPackage","line":511,"method":null,"native":false},{"column":18,"file":"node:internal/modules/cjs/loader","function":"Function._findPath","line":796,"method":"_findPath","native":false},{"column":27,"file":"node:internal/modules/cjs/loader","function":"Function._resolveFilename","line":1387,"method":"_resolveFilename","native":false},{"column":19,"file":"node:internal/modules/cjs/loader","function":"defaultResolveImpl","line":1057,"method":null,"native":false},{"column":22,"file":"node:internal/modules/cjs/loader","function":"resolveForCJSWithHooks","line":1062,"method":null,"native":false},{"column":37,"file":"node:internal/modules/cjs/loader","function":"Function._load","line":1211,"method":"_load","native":false},{"column":14,"file":"node:diagnostics_channel","function":"TracingChannel.traceSync","line":322,"method":"traceSync","native":false},{"column":24,"file":"node:internal/modules/cjs/loader","function":"wrapModuleLoad","line":235,"method":null,"native":false},{"column":12,"file":"node:internal/modules/cjs/loader","function":"Module.require","line":1487,"method":"require","native":false},{"column":16,"file":"node:internal/modules/helpers","function":"require","line":135,"method":null,"native":false}]}
64
+ {"date":"Tue Nov 18 2025 11:23:35 GMT+0100 (Central European Standard Time)","error":{"code":"ERR_PACKAGE_PATH_NOT_EXPORTED"},"level":"error","message":"unhandledRejection: No \"exports\" main defined in /Users/toby/Code/claudette/runner/node_modules/@northflare/codex-sdk/package.json\nError [ERR_PACKAGE_PATH_NOT_EXPORTED]: No \"exports\" main defined in /Users/toby/Code/claudette/runner/node_modules/@northflare/codex-sdk/package.json\n at exportsNotFound (node:internal/modules/esm/resolve:314:10)\n at packageExportsResolve (node:internal/modules/esm/resolve:604:13)\n at resolveExports (node:internal/modules/cjs/loader:657:36)\n at Function._findPath (node:internal/modules/cjs/loader:749:31)\n at Function._resolveFilename (node:internal/modules/cjs/loader:1387:27)\n at defaultResolveImpl (node:internal/modules/cjs/loader:1057:19)\n at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1062:22)\n at Function._load (node:internal/modules/cjs/loader:1211:37)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)","os":{"loadavg":[4.82373046875,4.37255859375,4.115234375],"uptime":97198},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/northflare-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":18675,"external":2091282,"heapTotal":18972672,"heapUsed":12330016,"rss":65404928},"pid":95991,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No \"exports\" main defined in /Users/toby/Code/claudette/runner/node_modules/@northflare/codex-sdk/package.json\n at exportsNotFound (node:internal/modules/esm/resolve:314:10)\n at packageExportsResolve (node:internal/modules/esm/resolve:604:13)\n at resolveExports (node:internal/modules/cjs/loader:657:36)\n at Function._findPath (node:internal/modules/cjs/loader:749:31)\n at Function._resolveFilename (node:internal/modules/cjs/loader:1387:27)\n at defaultResolveImpl (node:internal/modules/cjs/loader:1057:19)\n at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1062:22)\n at Function._load (node:internal/modules/cjs/loader:1211:37)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)","trace":[{"column":10,"file":"node:internal/modules/esm/resolve","function":"exportsNotFound","line":314,"method":null,"native":false},{"column":13,"file":"node:internal/modules/esm/resolve","function":"packageExportsResolve","line":604,"method":null,"native":false},{"column":36,"file":"node:internal/modules/cjs/loader","function":"resolveExports","line":657,"method":null,"native":false},{"column":31,"file":"node:internal/modules/cjs/loader","function":"Function._findPath","line":749,"method":"_findPath","native":false},{"column":27,"file":"node:internal/modules/cjs/loader","function":"Function._resolveFilename","line":1387,"method":"_resolveFilename","native":false},{"column":19,"file":"node:internal/modules/cjs/loader","function":"defaultResolveImpl","line":1057,"method":null,"native":false},{"column":22,"file":"node:internal/modules/cjs/loader","function":"resolveForCJSWithHooks","line":1062,"method":null,"native":false},{"column":37,"file":"node:internal/modules/cjs/loader","function":"Function._load","line":1211,"method":"_load","native":false},{"column":14,"file":"node:diagnostics_channel","function":"TracingChannel.traceSync","line":322,"method":"traceSync","native":false},{"column":24,"file":"node:internal/modules/cjs/loader","function":"wrapModuleLoad","line":235,"method":null,"native":false}]}
65
+ {"date":"Tue Nov 18 2025 11:24:17 GMT+0100 (Central European Standard Time)","error":{"code":"ERR_PACKAGE_PATH_NOT_EXPORTED"},"level":"error","message":"unhandledRejection: No \"exports\" main defined in /Users/toby/Code/claudette/runner/node_modules/@northflare/codex-sdk/package.json\nError [ERR_PACKAGE_PATH_NOT_EXPORTED]: No \"exports\" main defined in /Users/toby/Code/claudette/runner/node_modules/@northflare/codex-sdk/package.json\n at exportsNotFound (node:internal/modules/esm/resolve:314:10)\n at packageExportsResolve (node:internal/modules/esm/resolve:604:13)\n at resolveExports (node:internal/modules/cjs/loader:657:36)\n at Function._findPath (node:internal/modules/cjs/loader:749:31)\n at Function._resolveFilename (node:internal/modules/cjs/loader:1387:27)\n at defaultResolveImpl (node:internal/modules/cjs/loader:1057:19)\n at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1062:22)\n at Function._load (node:internal/modules/cjs/loader:1211:37)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)","os":{"loadavg":[7.13623046875,4.9140625,4.31787109375],"uptime":97240},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/northflare-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":18675,"external":2091282,"heapTotal":18710528,"heapUsed":12265536,"rss":65486848},"pid":99528,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No \"exports\" main defined in /Users/toby/Code/claudette/runner/node_modules/@northflare/codex-sdk/package.json\n at exportsNotFound (node:internal/modules/esm/resolve:314:10)\n at packageExportsResolve (node:internal/modules/esm/resolve:604:13)\n at resolveExports (node:internal/modules/cjs/loader:657:36)\n at Function._findPath (node:internal/modules/cjs/loader:749:31)\n at Function._resolveFilename (node:internal/modules/cjs/loader:1387:27)\n at defaultResolveImpl (node:internal/modules/cjs/loader:1057:19)\n at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1062:22)\n at Function._load (node:internal/modules/cjs/loader:1211:37)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)","trace":[{"column":10,"file":"node:internal/modules/esm/resolve","function":"exportsNotFound","line":314,"method":null,"native":false},{"column":13,"file":"node:internal/modules/esm/resolve","function":"packageExportsResolve","line":604,"method":null,"native":false},{"column":36,"file":"node:internal/modules/cjs/loader","function":"resolveExports","line":657,"method":null,"native":false},{"column":31,"file":"node:internal/modules/cjs/loader","function":"Function._findPath","line":749,"method":"_findPath","native":false},{"column":27,"file":"node:internal/modules/cjs/loader","function":"Function._resolveFilename","line":1387,"method":"_resolveFilename","native":false},{"column":19,"file":"node:internal/modules/cjs/loader","function":"defaultResolveImpl","line":1057,"method":null,"native":false},{"column":22,"file":"node:internal/modules/cjs/loader","function":"resolveForCJSWithHooks","line":1062,"method":null,"native":false},{"column":37,"file":"node:internal/modules/cjs/loader","function":"Function._load","line":1211,"method":"_load","native":false},{"column":14,"file":"node:diagnostics_channel","function":"TracingChannel.traceSync","line":322,"method":"traceSync","native":false},{"column":24,"file":"node:internal/modules/cjs/loader","function":"wrapModuleLoad","line":235,"method":null,"native":false}]}
66
+ {"date":"Wed Nov 19 2025 04:00:21 GMT+0100 (Central European Standard Time)","error":{},"level":"error","message":"unhandledRejection: Cannot access 'debug_1' before initialization\nReferenceError: Cannot access 'debug_1' before initialization\n at new StatusLineManager (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:19:39)\n at Object.<anonymous> (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:112:29)\n at Module._compile (node:internal/modules/cjs/loader:1730:14)\n at Object..js (node:internal/modules/cjs/loader:1895:10)\n at Module.load (node:internal/modules/cjs/loader:1465:32)\n at Function._load (node:internal/modules/cjs/loader:1282:12)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","os":{"loadavg":[4.80712890625,4.451171875,4.53564453125],"uptime":157004},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/northflare-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":12531,"external":1652665,"heapTotal":11091968,"heapUsed":6918376,"rss":54345728},"pid":4913,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"ReferenceError: Cannot access 'debug_1' before initialization\n at new StatusLineManager (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:19:39)\n at Object.<anonymous> (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:112:29)\n at Module._compile (node:internal/modules/cjs/loader:1730:14)\n at Object..js (node:internal/modules/cjs/loader:1895:10)\n at Module.load (node:internal/modules/cjs/loader:1465:32)\n at Function._load (node:internal/modules/cjs/loader:1282:12)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","trace":[{"column":39,"file":"/Users/toby/Code/claudette/runner/dist/utils/status-line.js","function":"new StatusLineManager","line":19,"method":null,"native":false},{"column":29,"file":"/Users/toby/Code/claudette/runner/dist/utils/status-line.js","function":null,"line":112,"method":null,"native":false},{"column":14,"file":"node:internal/modules/cjs/loader","function":"Module._compile","line":1730,"method":"_compile","native":false},{"column":10,"file":"node:internal/modules/cjs/loader","function":"Object..js","line":1895,"method":".js","native":false},{"column":32,"file":"node:internal/modules/cjs/loader","function":"Module.load","line":1465,"method":"load","native":false},{"column":12,"file":"node:internal/modules/cjs/loader","function":"Function._load","line":1282,"method":"_load","native":false},{"column":14,"file":"node:diagnostics_channel","function":"TracingChannel.traceSync","line":322,"method":"traceSync","native":false},{"column":24,"file":"node:internal/modules/cjs/loader","function":"wrapModuleLoad","line":235,"method":null,"native":false},{"column":12,"file":"node:internal/modules/cjs/loader","function":"Module.require","line":1487,"method":"require","native":false},{"column":16,"file":"node:internal/modules/helpers","function":"require","line":135,"method":null,"native":false}]}
67
+ {"date":"Wed Nov 19 2025 04:01:10 GMT+0100 (Central European Standard Time)","error":{},"level":"error","message":"unhandledRejection: Cannot access 'debug_1' before initialization\nReferenceError: Cannot access 'debug_1' before initialization\n at new StatusLineManager (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:19:39)\n at Object.<anonymous> (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:112:29)\n at Module._compile (node:internal/modules/cjs/loader:1730:14)\n at Object..js (node:internal/modules/cjs/loader:1895:10)\n at Module.load (node:internal/modules/cjs/loader:1465:32)\n at Function._load (node:internal/modules/cjs/loader:1282:12)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","os":{"loadavg":[4.14501953125,4.3193359375,4.48046875],"uptime":157053},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/northflare-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":12531,"external":1652665,"heapTotal":11091968,"heapUsed":6903192,"rss":55017472},"pid":8705,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"ReferenceError: Cannot access 'debug_1' before initialization\n at new StatusLineManager (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:19:39)\n at Object.<anonymous> (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:112:29)\n at Module._compile (node:internal/modules/cjs/loader:1730:14)\n at Object..js (node:internal/modules/cjs/loader:1895:10)\n at Module.load (node:internal/modules/cjs/loader:1465:32)\n at Function._load (node:internal/modules/cjs/loader:1282:12)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","trace":[{"column":39,"file":"/Users/toby/Code/claudette/runner/dist/utils/status-line.js","function":"new StatusLineManager","line":19,"method":null,"native":false},{"column":29,"file":"/Users/toby/Code/claudette/runner/dist/utils/status-line.js","function":null,"line":112,"method":null,"native":false},{"column":14,"file":"node:internal/modules/cjs/loader","function":"Module._compile","line":1730,"method":"_compile","native":false},{"column":10,"file":"node:internal/modules/cjs/loader","function":"Object..js","line":1895,"method":".js","native":false},{"column":32,"file":"node:internal/modules/cjs/loader","function":"Module.load","line":1465,"method":"load","native":false},{"column":12,"file":"node:internal/modules/cjs/loader","function":"Function._load","line":1282,"method":"_load","native":false},{"column":14,"file":"node:diagnostics_channel","function":"TracingChannel.traceSync","line":322,"method":"traceSync","native":false},{"column":24,"file":"node:internal/modules/cjs/loader","function":"wrapModuleLoad","line":235,"method":null,"native":false},{"column":12,"file":"node:internal/modules/cjs/loader","function":"Module.require","line":1487,"method":"require","native":false},{"column":16,"file":"node:internal/modules/helpers","function":"require","line":135,"method":null,"native":false}]}
68
+ {"date":"Wed Nov 19 2025 04:01:13 GMT+0100 (Central European Standard Time)","error":{},"level":"error","message":"unhandledRejection: Cannot access 'debug_1' before initialization\nReferenceError: Cannot access 'debug_1' before initialization\n at new StatusLineManager (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:19:39)\n at Object.<anonymous> (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:112:29)\n at Module._compile (node:internal/modules/cjs/loader:1730:14)\n at Object..js (node:internal/modules/cjs/loader:1895:10)\n at Module.load (node:internal/modules/cjs/loader:1465:32)\n at Function._load (node:internal/modules/cjs/loader:1282:12)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","os":{"loadavg":[4.53369140625,4.39697265625,4.5068359375],"uptime":157056},"process":{"argv":["/Users/toby/.nvm/versions/node/v22.15.0/bin/node","/Users/toby/Code/claudette/runner/bin/northflare-runner"],"cwd":"/Users/toby/Code/claudette/runner","execPath":"/Users/toby/.nvm/versions/node/v22.15.0/bin/node","gid":20,"memoryUsage":{"arrayBuffers":12531,"external":1652665,"heapTotal":11091968,"heapUsed":6909192,"rss":55214080},"pid":8860,"uid":501,"version":"v22.15.0"},"rejection":true,"stack":"ReferenceError: Cannot access 'debug_1' before initialization\n at new StatusLineManager (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:19:39)\n at Object.<anonymous> (/Users/toby/Code/claudette/runner/dist/utils/status-line.js:112:29)\n at Module._compile (node:internal/modules/cjs/loader:1730:14)\n at Object..js (node:internal/modules/cjs/loader:1895:10)\n at Module.load (node:internal/modules/cjs/loader:1465:32)\n at Function._load (node:internal/modules/cjs/loader:1282:12)\n at TracingChannel.traceSync (node:diagnostics_channel:322:14)\n at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)\n at Module.require (node:internal/modules/cjs/loader:1487:12)\n at require (node:internal/modules/helpers:135:16)","trace":[{"column":39,"file":"/Users/toby/Code/claudette/runner/dist/utils/status-line.js","function":"new StatusLineManager","line":19,"method":null,"native":false},{"column":29,"file":"/Users/toby/Code/claudette/runner/dist/utils/status-line.js","function":null,"line":112,"method":null,"native":false},{"column":14,"file":"node:internal/modules/cjs/loader","function":"Module._compile","line":1730,"method":"_compile","native":false},{"column":10,"file":"node:internal/modules/cjs/loader","function":"Object..js","line":1895,"method":".js","native":false},{"column":32,"file":"node:internal/modules/cjs/loader","function":"Module.load","line":1465,"method":"load","native":false},{"column":12,"file":"node:internal/modules/cjs/loader","function":"Function._load","line":1282,"method":"_load","native":false},{"column":14,"file":"node:diagnostics_channel","function":"TracingChannel.traceSync","line":322,"method":"traceSync","native":false},{"column":24,"file":"node:internal/modules/cjs/loader","function":"wrapModuleLoad","line":235,"method":null,"native":false},{"column":12,"file":"node:internal/modules/cjs/loader","function":"Module.require","line":1487,"method":"require","native":false},{"column":16,"file":"node:internal/modules/helpers","function":"require","line":135,"method":null,"native":false}]}
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  import { query as sdkQuery } from "@anthropic-ai/claude-agent-sdk";
18
+ import type { Conversation as ClaudeConversation } from "@botanicastudios/claude-code-sdk-ts";
18
19
  // Keep SDKMessage loosely typed to avoid tight coupling to SDK typings
19
20
  type SDKMessage = any;
20
21
  import { IRunnerApp } from "../types/runner-interface";
@@ -23,6 +24,7 @@ import { ConversationContext, ConversationConfig, Message } from "../types";
23
24
  import { statusLineManager } from "../utils/status-line";
24
25
  import { console } from "../utils/console";
25
26
  import { expandEnv } from "../utils/expand-env";
27
+ import { isRunnerDebugEnabled } from "../utils/debug";
26
28
  import * as jwt from "jsonwebtoken";
27
29
 
28
30
  export class ClaudeManager {
@@ -37,7 +39,7 @@ export class ClaudeManager {
37
39
  this.repositoryManager = repositoryManager;
38
40
 
39
41
  // Log debug mode status
40
- if (process.env["DEBUG"] === "true") {
42
+ if (isRunnerDebugEnabled()) {
41
43
  console.log(
42
44
  "[ClaudeManager] DEBUG MODE ENABLED - Claude SDK will log verbose output"
43
45
  );
@@ -255,7 +257,7 @@ export class ClaudeManager {
255
257
  envVars["GITHUB_TOKEN"] = githubToken;
256
258
  }
257
259
 
258
- if (process.env["DEBUG"] === "true") {
260
+ if (isRunnerDebugEnabled()) {
259
261
  envVars["DEBUG"] = "1";
260
262
  }
261
263
 
@@ -301,11 +303,11 @@ export class ClaudeManager {
301
303
  // Simplified MCP server configuration
302
304
  let mcpServers: Record<string, any> | undefined;
303
305
  if (config.mcpServers) {
306
+ mcpServers = expandEnv(config.mcpServers, { TOOL_TOKEN: toolToken });
304
307
  console.log(
305
308
  "[ClaudeManager] MCP servers configuration:",
306
- JSON.stringify(config.mcpServers, null, 2)
309
+ JSON.stringify(mcpServers, null, 2)
307
310
  );
308
- mcpServers = expandEnv(config.mcpServers, { TOOL_TOKEN: toolToken });
309
311
  }
310
312
 
311
313
  // Create input stream for user messages (simplified message queueing)
@@ -333,7 +335,7 @@ export class ClaudeManager {
333
335
  : {}),
334
336
  ...(disallowedTools.length ? { disallowedTools } : {}),
335
337
  ...(mcpServers ? { mcpServers } : {}),
336
- ...(process.env["DEBUG"] === "true"
338
+ ...(isRunnerDebugEnabled()
337
339
  ? {
338
340
  stderr: (data: string) => {
339
341
  try {
@@ -473,7 +475,9 @@ export class ClaudeManager {
473
475
  context.status = "stopped";
474
476
 
475
477
  // Properly end the conversation using the SDK
476
- await context.conversation.end();
478
+ if (isClaudeConversation(context.conversation)) {
479
+ await context.conversation.end();
480
+ }
477
481
  } catch (error) {
478
482
  console.error(`Error ending conversation ${agentSessionId}:`, error);
479
483
  }
@@ -508,7 +512,7 @@ export class ClaudeManager {
508
512
 
509
513
  // After starting the conversation with the sessionId, we need to send a message
510
514
  // to actually trigger the Claude process to continue
511
- if (context.conversation) {
515
+ if (context.conversation && isClaudeConversation(context.conversation)) {
512
516
  try {
513
517
  // Use the provided resume message or default to system instruction
514
518
  const messageToSend =
@@ -524,6 +528,10 @@ export class ClaudeManager {
524
528
  } catch (error) {
525
529
  console.error(`[ClaudeManager] Error sending resume message:`, error);
526
530
  }
531
+ } else {
532
+ console.warn(
533
+ "[ClaudeManager] Resume requested but conversation instance missing or incompatible"
534
+ );
527
535
  }
528
536
 
529
537
  return context.agentSessionId;
@@ -573,7 +581,8 @@ export class ClaudeManager {
573
581
  config?: ConversationConfig,
574
582
  conversationObjectType?: "Task" | "TaskPlan",
575
583
  conversationObjectId?: string,
576
- conversation?: any
584
+ conversation?: any,
585
+ _agentSessionIdOverride?: string
577
586
  ): Promise<void> {
578
587
  console.log(`[ClaudeManager] sendUserMessage called with:`, {
579
588
  conversationId,
@@ -644,7 +653,7 @@ export class ClaudeManager {
644
653
 
645
654
  try {
646
655
  // Send immediately when a conversation instance exists; no need to wait for "active"
647
- if (!context.conversation) {
656
+ if (!context.conversation || !isClaudeConversation(context.conversation)) {
648
657
  throw new Error(
649
658
  `No conversation instance found for conversation ${context.conversationId}`
650
659
  );
@@ -670,7 +679,7 @@ export class ClaudeManager {
670
679
  // Native message injection - SDK handles queueing and delivery
671
680
  const normalizedText = this.normalizeToText(content);
672
681
 
673
- if (process.env["DEBUG"] === "true") {
682
+ if (isRunnerDebugEnabled()) {
674
683
  console.log("[ClaudeManager] Normalized follow-up content", {
675
684
  originalType: typeof content,
676
685
  isArray: Array.isArray(content) || undefined,
@@ -980,14 +989,17 @@ export class ClaudeManager {
980
989
  }
981
990
 
982
991
  case "thinking" as any: {
983
- // Map thinking to assistant with subtype
984
- messageType = "assistant";
985
- subtype = "thinking";
992
+ messageType = "thinking";
993
+ subtype = undefined;
986
994
  const thinkingMsg = message as any;
987
- structuredContent = {
988
- text: thinkingMsg.content || "",
989
- timestamp: new Date().toISOString(),
990
- };
995
+ structuredContent = [
996
+ {
997
+ type: "thinking",
998
+ thinking: thinkingMsg.content || "",
999
+ text: thinkingMsg.content || "",
1000
+ timestamp: new Date().toISOString(),
1001
+ },
1002
+ ];
991
1003
  break;
992
1004
  }
993
1005
 
@@ -1402,3 +1414,12 @@ function createConversationWrapper(
1402
1414
  },
1403
1415
  };
1404
1416
  }
1417
+ function isClaudeConversation(
1418
+ conversation: ConversationContext["conversation"]
1419
+ ): conversation is ClaudeConversation {
1420
+ return (
1421
+ !!conversation &&
1422
+ typeof (conversation as ClaudeConversation).send === "function" &&
1423
+ typeof (conversation as ClaudeConversation).end === "function"
1424
+ );
1425
+ }