@northflare/runner 0.0.11 → 0.0.13
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/dist/utils/config.d.ts +1 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +13 -2
- package/dist/utils/config.js.map +1 -1
- package/package.json +1 -2
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/coverage-final.json +0 -12
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -176
- package/coverage/lib/index.html +0 -116
- package/coverage/lib/preload-script.js.html +0 -964
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
- package/coverage/src/collections/index.html +0 -116
- package/coverage/src/collections/runner-messages.ts.html +0 -312
- package/coverage/src/components/claude-manager.ts.html +0 -1290
- package/coverage/src/components/index.html +0 -146
- package/coverage/src/components/message-handler.ts.html +0 -730
- package/coverage/src/components/repository-manager.ts.html +0 -841
- package/coverage/src/index.html +0 -131
- package/coverage/src/index.ts.html +0 -448
- package/coverage/src/runner.ts.html +0 -1239
- package/coverage/src/utils/config.ts.html +0 -780
- package/coverage/src/utils/console.ts.html +0 -121
- package/coverage/src/utils/index.html +0 -161
- package/coverage/src/utils/logger.ts.html +0 -475
- package/coverage/src/utils/status-line.ts.html +0 -445
- package/exceptions.log +0 -24
- package/lib/codex-sdk/src/codex.ts +0 -38
- package/lib/codex-sdk/src/codexOptions.ts +0 -10
- package/lib/codex-sdk/src/events.ts +0 -80
- package/lib/codex-sdk/src/exec.ts +0 -336
- package/lib/codex-sdk/src/index.ts +0 -39
- package/lib/codex-sdk/src/items.ts +0 -127
- package/lib/codex-sdk/src/outputSchemaFile.ts +0 -40
- package/lib/codex-sdk/src/thread.ts +0 -155
- package/lib/codex-sdk/src/threadOptions.ts +0 -18
- package/lib/codex-sdk/src/turnOptions.ts +0 -6
- package/lib/codex-sdk/tests/abort.test.ts +0 -165
- package/lib/codex-sdk/tests/codexExecSpy.ts +0 -37
- package/lib/codex-sdk/tests/responsesProxy.ts +0 -225
- package/lib/codex-sdk/tests/run.test.ts +0 -687
- package/lib/codex-sdk/tests/runStreamed.test.ts +0 -211
- package/lib/codex-sdk/tsconfig.json +0 -24
- package/rejections.log +0 -68
- package/runner.log +0 -488
- package/src/components/claude-sdk-manager.ts +0 -1425
- package/src/components/codex-sdk-manager.ts +0 -1358
- package/src/components/enhanced-repository-manager.ts +0 -823
- package/src/components/message-handler-sse.ts +0 -1097
- package/src/components/repository-manager.ts +0 -337
- package/src/index.ts +0 -168
- package/src/runner-sse.ts +0 -917
- package/src/services/RunnerAPIClient.ts +0 -175
- package/src/services/SSEClient.ts +0 -258
- package/src/types/claude.ts +0 -66
- package/src/types/computer-name.d.ts +0 -4
- package/src/types/index.ts +0 -64
- package/src/types/messages.ts +0 -39
- package/src/types/runner-interface.ts +0 -36
- package/src/utils/StateManager.ts +0 -187
- package/src/utils/config.ts +0 -316
- package/src/utils/console.ts +0 -15
- package/src/utils/debug.ts +0 -18
- package/src/utils/expand-env.ts +0 -22
- package/src/utils/logger.ts +0 -134
- package/src/utils/model.ts +0 -29
- package/src/utils/status-line.ts +0 -122
- package/src/utils/tool-response-sanitizer.ts +0 -160
- package/test-debug.sh +0 -26
- package/tests/retry-strategies.test.ts +0 -410
- package/tests/sdk-integration.test.ts +0 -329
- package/tests/sdk-streaming.test.ts +0 -1180
- package/tests/setup.ts +0 -5
- package/tests/test-claude-manager.ts +0 -120
- package/tests/tool-response-sanitizer.test.ts +0 -63
- package/tsconfig.json +0 -36
- package/vitest.config.ts +0 -27
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export type ApprovalMode = "never" | "on-request" | "on-failure" | "untrusted";
|
|
2
|
-
|
|
3
|
-
export type SandboxMode = "read-only" | "workspace-write" | "danger-full-access";
|
|
4
|
-
|
|
5
|
-
export type ModelReasoningEffort = "minimal" | "low" | "medium" | "high";
|
|
6
|
-
|
|
7
|
-
export type ThreadOptions = {
|
|
8
|
-
model?: string;
|
|
9
|
-
sandboxMode?: SandboxMode;
|
|
10
|
-
workingDirectory?: string;
|
|
11
|
-
skipGitRepoCheck?: boolean;
|
|
12
|
-
modelReasoningEffort?: ModelReasoningEffort;
|
|
13
|
-
networkAccessEnabled?: boolean;
|
|
14
|
-
webSearchEnabled?: boolean;
|
|
15
|
-
approvalPolicy?: ApprovalMode;
|
|
16
|
-
additionalDirectories?: string[];
|
|
17
|
-
configOverrides?: Record<string, unknown>;
|
|
18
|
-
};
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
|
|
3
|
-
import { describe, expect, it } from "@jest/globals";
|
|
4
|
-
|
|
5
|
-
import { Codex } from "../src/codex";
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
assistantMessage,
|
|
9
|
-
responseCompleted,
|
|
10
|
-
responseStarted,
|
|
11
|
-
shell_call as shellCall,
|
|
12
|
-
sse,
|
|
13
|
-
SseResponseBody,
|
|
14
|
-
startResponsesTestProxy,
|
|
15
|
-
} from "./responsesProxy";
|
|
16
|
-
|
|
17
|
-
const codexExecPath = path.join(process.cwd(), "..", "..", "codex-rs", "target", "debug", "codex");
|
|
18
|
-
|
|
19
|
-
function* infiniteShellCall(): Generator<SseResponseBody> {
|
|
20
|
-
while (true) {
|
|
21
|
-
yield sse(responseStarted(), shellCall(), responseCompleted());
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
describe("AbortSignal support", () => {
|
|
26
|
-
it("aborts run() when signal is aborted", async () => {
|
|
27
|
-
const { url, close } = await startResponsesTestProxy({
|
|
28
|
-
statusCode: 200,
|
|
29
|
-
responseBodies: infiniteShellCall(),
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
|
|
34
|
-
const thread = client.startThread();
|
|
35
|
-
|
|
36
|
-
// Create an abort controller and abort it immediately
|
|
37
|
-
const controller = new AbortController();
|
|
38
|
-
controller.abort("Test abort");
|
|
39
|
-
|
|
40
|
-
// The operation should fail because the signal is already aborted
|
|
41
|
-
await expect(thread.run("Hello, world!", { signal: controller.signal })).rejects.toThrow();
|
|
42
|
-
} finally {
|
|
43
|
-
await close();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("aborts runStreamed() when signal is aborted", async () => {
|
|
48
|
-
const { url, close } = await startResponsesTestProxy({
|
|
49
|
-
statusCode: 200,
|
|
50
|
-
responseBodies: infiniteShellCall(),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
|
|
55
|
-
const thread = client.startThread();
|
|
56
|
-
|
|
57
|
-
// Create an abort controller and abort it immediately
|
|
58
|
-
const controller = new AbortController();
|
|
59
|
-
controller.abort("Test abort");
|
|
60
|
-
|
|
61
|
-
const { events } = await thread.runStreamed("Hello, world!", { signal: controller.signal });
|
|
62
|
-
|
|
63
|
-
// Attempting to iterate should fail
|
|
64
|
-
let iterationStarted = false;
|
|
65
|
-
try {
|
|
66
|
-
for await (const event of events) {
|
|
67
|
-
iterationStarted = true;
|
|
68
|
-
// Should not get here
|
|
69
|
-
expect(event).toBeUndefined();
|
|
70
|
-
}
|
|
71
|
-
// If we get here, the test should fail
|
|
72
|
-
throw new Error(
|
|
73
|
-
"Expected iteration to throw due to aborted signal, but it completed successfully",
|
|
74
|
-
);
|
|
75
|
-
} catch (error) {
|
|
76
|
-
// We expect an error to be thrown
|
|
77
|
-
expect(iterationStarted).toBe(false); // Should fail before any iteration
|
|
78
|
-
expect(error).toBeDefined();
|
|
79
|
-
}
|
|
80
|
-
} finally {
|
|
81
|
-
await close();
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("aborts run() when signal is aborted during execution", async () => {
|
|
86
|
-
const { url, close } = await startResponsesTestProxy({
|
|
87
|
-
statusCode: 200,
|
|
88
|
-
responseBodies: infiniteShellCall(),
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
|
|
93
|
-
const thread = client.startThread();
|
|
94
|
-
|
|
95
|
-
const controller = new AbortController();
|
|
96
|
-
|
|
97
|
-
// Start the operation and abort it immediately after
|
|
98
|
-
const runPromise = thread.run("Hello, world!", { signal: controller.signal });
|
|
99
|
-
|
|
100
|
-
// Abort after a tiny delay to simulate aborting during execution
|
|
101
|
-
setTimeout(() => controller.abort("Aborted during execution"), 10);
|
|
102
|
-
|
|
103
|
-
// The operation should fail
|
|
104
|
-
await expect(runPromise).rejects.toThrow();
|
|
105
|
-
} finally {
|
|
106
|
-
await close();
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("aborts runStreamed() when signal is aborted during iteration", async () => {
|
|
111
|
-
const { url, close } = await startResponsesTestProxy({
|
|
112
|
-
statusCode: 200,
|
|
113
|
-
responseBodies: infiniteShellCall(),
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
try {
|
|
117
|
-
const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
|
|
118
|
-
const thread = client.startThread();
|
|
119
|
-
|
|
120
|
-
const controller = new AbortController();
|
|
121
|
-
|
|
122
|
-
const { events } = await thread.runStreamed("Hello, world!", { signal: controller.signal });
|
|
123
|
-
|
|
124
|
-
// Abort during iteration
|
|
125
|
-
let eventCount = 0;
|
|
126
|
-
await expect(
|
|
127
|
-
(async () => {
|
|
128
|
-
for await (const event of events) {
|
|
129
|
-
void event; // Consume the event
|
|
130
|
-
eventCount++;
|
|
131
|
-
// Abort after first event
|
|
132
|
-
if (eventCount === 5) {
|
|
133
|
-
controller.abort("Aborted during iteration");
|
|
134
|
-
}
|
|
135
|
-
// Continue iterating - should eventually throw
|
|
136
|
-
}
|
|
137
|
-
})(),
|
|
138
|
-
).rejects.toThrow();
|
|
139
|
-
} finally {
|
|
140
|
-
await close();
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("completes normally when signal is not aborted", async () => {
|
|
145
|
-
const { url, close } = await startResponsesTestProxy({
|
|
146
|
-
statusCode: 200,
|
|
147
|
-
responseBodies: [sse(responseStarted(), assistantMessage("Hi!"), responseCompleted())],
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
|
|
152
|
-
const thread = client.startThread();
|
|
153
|
-
|
|
154
|
-
const controller = new AbortController();
|
|
155
|
-
|
|
156
|
-
// Don't abort - should complete successfully
|
|
157
|
-
const result = await thread.run("Hello, world!", { signal: controller.signal });
|
|
158
|
-
|
|
159
|
-
expect(result.finalResponse).toBe("Hi!");
|
|
160
|
-
expect(result.items).toHaveLength(1);
|
|
161
|
-
} finally {
|
|
162
|
-
await close();
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import * as child_process from "node:child_process";
|
|
2
|
-
|
|
3
|
-
jest.mock("node:child_process", () => {
|
|
4
|
-
const actual = jest.requireActual<typeof import("node:child_process")>("node:child_process");
|
|
5
|
-
return { ...actual, spawn: jest.fn(actual.spawn) };
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
const actualChildProcess =
|
|
9
|
-
jest.requireActual<typeof import("node:child_process")>("node:child_process");
|
|
10
|
-
const spawnMock = child_process.spawn as jest.MockedFunction<typeof actualChildProcess.spawn>;
|
|
11
|
-
|
|
12
|
-
export function codexExecSpy(): {
|
|
13
|
-
args: string[][];
|
|
14
|
-
envs: (Record<string, string> | undefined)[];
|
|
15
|
-
restore: () => void;
|
|
16
|
-
} {
|
|
17
|
-
const previousImplementation = spawnMock.getMockImplementation() ?? actualChildProcess.spawn;
|
|
18
|
-
const args: string[][] = [];
|
|
19
|
-
const envs: (Record<string, string> | undefined)[] = [];
|
|
20
|
-
|
|
21
|
-
spawnMock.mockImplementation(((...spawnArgs: Parameters<typeof child_process.spawn>) => {
|
|
22
|
-
const commandArgs = spawnArgs[1];
|
|
23
|
-
args.push(Array.isArray(commandArgs) ? [...commandArgs] : []);
|
|
24
|
-
const options = spawnArgs[2] as child_process.SpawnOptions | undefined;
|
|
25
|
-
envs.push(options?.env as Record<string, string> | undefined);
|
|
26
|
-
return previousImplementation(...spawnArgs);
|
|
27
|
-
}) as typeof actualChildProcess.spawn);
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
args,
|
|
31
|
-
envs,
|
|
32
|
-
restore: () => {
|
|
33
|
-
spawnMock.mockClear();
|
|
34
|
-
spawnMock.mockImplementation(previousImplementation);
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
}
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
|
|
3
|
-
const DEFAULT_RESPONSE_ID = "resp_mock";
|
|
4
|
-
const DEFAULT_MESSAGE_ID = "msg_mock";
|
|
5
|
-
|
|
6
|
-
type ResponseCompletedUsage = {
|
|
7
|
-
input_tokens: number;
|
|
8
|
-
input_tokens_details: { cached_tokens: number } | null;
|
|
9
|
-
output_tokens: number;
|
|
10
|
-
output_tokens_details: { reasoning_tokens: number } | null;
|
|
11
|
-
total_tokens: number;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const DEFAULT_COMPLETED_USAGE: ResponseCompletedUsage = {
|
|
15
|
-
input_tokens: 42,
|
|
16
|
-
input_tokens_details: { cached_tokens: 12 },
|
|
17
|
-
output_tokens: 5,
|
|
18
|
-
output_tokens_details: null,
|
|
19
|
-
total_tokens: 47,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type SseEvent = {
|
|
23
|
-
type: string;
|
|
24
|
-
[key: string]: unknown;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export type SseResponseBody = {
|
|
28
|
-
kind: "sse";
|
|
29
|
-
events: SseEvent[];
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export type ResponsesProxyOptions = {
|
|
33
|
-
responseBodies: Generator<SseResponseBody> | SseResponseBody[];
|
|
34
|
-
statusCode?: number;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export type ResponsesProxy = {
|
|
38
|
-
url: string;
|
|
39
|
-
close: () => Promise<void>;
|
|
40
|
-
requests: RecordedRequest[];
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export type ResponsesApiRequest = {
|
|
44
|
-
model?: string;
|
|
45
|
-
input: Array<{
|
|
46
|
-
role: string;
|
|
47
|
-
content?: Array<{ type: string; text: string }>;
|
|
48
|
-
}>;
|
|
49
|
-
text?: {
|
|
50
|
-
format?: Record<string, unknown>;
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export type RecordedRequest = {
|
|
55
|
-
body: string;
|
|
56
|
-
json: ResponsesApiRequest;
|
|
57
|
-
headers: http.IncomingHttpHeaders;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
function formatSseEvent(event: SseEvent): string {
|
|
61
|
-
return `event: ${event.type}\n` + `data: ${JSON.stringify(event)}\n\n`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export async function startResponsesTestProxy(
|
|
65
|
-
options: ResponsesProxyOptions,
|
|
66
|
-
): Promise<ResponsesProxy> {
|
|
67
|
-
function* createGenerator(array: SseResponseBody[]): Generator<SseResponseBody> {
|
|
68
|
-
for (const elem of array) {
|
|
69
|
-
yield elem;
|
|
70
|
-
}
|
|
71
|
-
throw new Error("not enough responses provided");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const responseBodies: Generator<SseResponseBody> = Array.isArray(options.responseBodies)
|
|
75
|
-
? createGenerator(options.responseBodies)
|
|
76
|
-
: options.responseBodies;
|
|
77
|
-
|
|
78
|
-
const requests: RecordedRequest[] = [];
|
|
79
|
-
|
|
80
|
-
function readRequestBody(req: http.IncomingMessage): Promise<string> {
|
|
81
|
-
return new Promise<string>((resolve, reject) => {
|
|
82
|
-
const chunks: Buffer[] = [];
|
|
83
|
-
req.on("data", (chunk) => {
|
|
84
|
-
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
85
|
-
});
|
|
86
|
-
req.on("end", () => {
|
|
87
|
-
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
88
|
-
});
|
|
89
|
-
req.on("error", reject);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const server = http.createServer((req, res) => {
|
|
94
|
-
async function handle(): Promise<void> {
|
|
95
|
-
if (req.method === "POST" && req.url === "/responses") {
|
|
96
|
-
const body = await readRequestBody(req);
|
|
97
|
-
const json = JSON.parse(body);
|
|
98
|
-
requests.push({ body, json, headers: { ...req.headers } });
|
|
99
|
-
|
|
100
|
-
const status = options.statusCode ?? 200;
|
|
101
|
-
res.statusCode = status;
|
|
102
|
-
res.setHeader("content-type", "text/event-stream");
|
|
103
|
-
|
|
104
|
-
const responseBody = responseBodies.next().value;
|
|
105
|
-
for (const event of responseBody.events) {
|
|
106
|
-
res.write(formatSseEvent(event));
|
|
107
|
-
}
|
|
108
|
-
res.end();
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
res.statusCode = 404;
|
|
113
|
-
res.end();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
handle().catch(() => {
|
|
117
|
-
res.statusCode = 500;
|
|
118
|
-
res.end();
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const url = await new Promise<string>((resolve, reject) => {
|
|
123
|
-
server.listen(0, "127.0.0.1", () => {
|
|
124
|
-
const address = server.address();
|
|
125
|
-
if (!address || typeof address === "string") {
|
|
126
|
-
reject(new Error("Unable to determine proxy address"));
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
server.off("error", reject);
|
|
130
|
-
const info = address;
|
|
131
|
-
resolve(`http://${info.address}:${info.port}`);
|
|
132
|
-
});
|
|
133
|
-
server.once("error", reject);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
async function close(): Promise<void> {
|
|
137
|
-
await new Promise<void>((resolve, reject) => {
|
|
138
|
-
server.close((err) => {
|
|
139
|
-
if (err) {
|
|
140
|
-
reject(err);
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
resolve();
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
return { url, close, requests };
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function sse(...events: SseEvent[]): SseResponseBody {
|
|
151
|
-
return {
|
|
152
|
-
kind: "sse",
|
|
153
|
-
events,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export function responseStarted(responseId: string = DEFAULT_RESPONSE_ID): SseEvent {
|
|
158
|
-
return {
|
|
159
|
-
type: "response.created",
|
|
160
|
-
response: {
|
|
161
|
-
id: responseId,
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export function assistantMessage(text: string, itemId: string = DEFAULT_MESSAGE_ID): SseEvent {
|
|
167
|
-
return {
|
|
168
|
-
type: "response.output_item.done",
|
|
169
|
-
item: {
|
|
170
|
-
type: "message",
|
|
171
|
-
role: "assistant",
|
|
172
|
-
id: itemId,
|
|
173
|
-
content: [
|
|
174
|
-
{
|
|
175
|
-
type: "output_text",
|
|
176
|
-
text,
|
|
177
|
-
},
|
|
178
|
-
],
|
|
179
|
-
},
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function shell_call(): SseEvent {
|
|
184
|
-
const command = ["bash", "-lc", "echo 'Hello, world!'"];
|
|
185
|
-
return {
|
|
186
|
-
type: "response.output_item.done",
|
|
187
|
-
item: {
|
|
188
|
-
type: "function_call",
|
|
189
|
-
call_id: `call_id${Math.random().toString(36).slice(2)}`,
|
|
190
|
-
name: "shell",
|
|
191
|
-
arguments: JSON.stringify({
|
|
192
|
-
command,
|
|
193
|
-
timeout_ms: 100,
|
|
194
|
-
}),
|
|
195
|
-
},
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export function responseFailed(errorMessage: string): SseEvent {
|
|
200
|
-
return {
|
|
201
|
-
type: "error",
|
|
202
|
-
error: { code: "rate_limit_exceeded", message: errorMessage },
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function responseCompleted(
|
|
207
|
-
responseId: string = DEFAULT_RESPONSE_ID,
|
|
208
|
-
usage: ResponseCompletedUsage = DEFAULT_COMPLETED_USAGE,
|
|
209
|
-
): SseEvent {
|
|
210
|
-
const inputDetails = usage.input_tokens_details ? { ...usage.input_tokens_details } : null;
|
|
211
|
-
const outputDetails = usage.output_tokens_details ? { ...usage.output_tokens_details } : null;
|
|
212
|
-
return {
|
|
213
|
-
type: "response.completed",
|
|
214
|
-
response: {
|
|
215
|
-
id: responseId,
|
|
216
|
-
usage: {
|
|
217
|
-
input_tokens: usage.input_tokens,
|
|
218
|
-
input_tokens_details: inputDetails,
|
|
219
|
-
output_tokens: usage.output_tokens,
|
|
220
|
-
output_tokens_details: outputDetails,
|
|
221
|
-
total_tokens: usage.total_tokens,
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
};
|
|
225
|
-
}
|