@btatum5/codex-bridge 0.1.0 → 1.3.3

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/server.mjs DELETED
@@ -1,290 +0,0 @@
1
- import { createServer } from "node:http";
2
-
3
- const args = process.argv.slice(2);
4
- const host = resolveHost(args);
5
- const port = Number(process.env.PORT || 8787);
6
-
7
- const state = {
8
- status: "ready",
9
- desktopName: "Windows 11 Codex",
10
- sessionName: "Primary Session",
11
- workspacePath: "C:\\Users\\bobby\\source\\project",
12
- model: "gpt-5.4",
13
- reasoningEffort: "high",
14
- approvalMode: "confirm_sensitive",
15
- fileAccess: "workspace_only",
16
- allowShellCommands: true,
17
- networkAccess: true,
18
- syncDesktopTranscript: true,
19
- activeTask: "Waiting for instructions from iPhone.",
20
- lastAssistantReply: "Desktop companion online.",
21
- lastMessage: null,
22
- lastUpdatedAt: new Date().toISOString(),
23
- pendingApprovals: [
24
- {
25
- id: "approval-write-workspace",
26
- title: "Approve Workspace Write",
27
- summary: "Codex wants permission to write changes into the active workspace.",
28
- command: "apply_patch workspace files",
29
- risk: "medium"
30
- }
31
- ],
32
- openFiles: [
33
- { path: "C:\\Users\\bobby\\source\\project\\README.md", status: "active" },
34
- { path: "C:\\Users\\bobby\\source\\project\\src\\App.tsx", status: "modified" },
35
- { path: "C:\\Users\\bobby\\source\\project\\package.json", status: "tracked" }
36
- ],
37
- terminalLines: [
38
- line("info", "$ codex --session \"Primary Session\""),
39
- line("info", "Desktop companion booted."),
40
- line("success", "Waiting for remote controller input.")
41
- ]
42
- };
43
-
44
- const server = createServer(async (req, res) => {
45
- try {
46
- const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
47
-
48
- if (req.method === "GET" && url.pathname === "/health") {
49
- return sendJson(res, 200, {
50
- status: state.status,
51
- message: "desktop companion online",
52
- session: state.sessionName,
53
- desktopName: state.desktopName,
54
- workspacePath: state.workspacePath,
55
- activeTask: state.activeTask,
56
- pendingApprovals: state.pendingApprovals.length
57
- });
58
- }
59
-
60
- if (req.method === "GET" && url.pathname === "/v1/companion/session") {
61
- return sendJson(res, 200, snapshot());
62
- }
63
-
64
- if (req.method === "POST" && url.pathname === "/v1/companion/settings") {
65
- const body = await readJson(req);
66
- applySettings(body);
67
- state.status = "ready";
68
- state.activeTask = "Desktop settings updated from iPhone.";
69
- state.lastAssistantReply = "Settings synced to the desktop companion.";
70
- appendTerminal("success", "Applied configuration update from iPhone.");
71
-
72
- return sendJson(res, 200, {
73
- message: "desktop companion applied the settings update",
74
- state: snapshot()
75
- });
76
- }
77
-
78
- if (req.method === "POST" && url.pathname === "/v1/companion/actions") {
79
- const body = await readJson(req);
80
- const result = applyAction(body);
81
-
82
- return sendJson(res, 200, {
83
- message: result,
84
- state: snapshot()
85
- });
86
- }
87
-
88
- if (req.method === "POST" && url.pathname === "/v1/companion/chat") {
89
- const body = await readJson(req);
90
- applySettings(body);
91
-
92
- state.status = "working";
93
- state.lastMessage = body.message || null;
94
- state.activeTask = body.message || "Executing desktop task from iPhone.";
95
- state.lastAssistantReply = "Desktop companion synced the latest controller instruction.";
96
- state.lastUpdatedAt = new Date().toISOString();
97
-
98
- if (body.message) {
99
- appendTerminal("info", `$ codex prompt "${body.message}"`);
100
- }
101
-
102
- maybeQueueApproval(body.message);
103
-
104
- const reply = [
105
- `Desktop target: ${state.desktopName}`,
106
- `Workspace: ${state.workspacePath}`,
107
- `Model: ${state.model}`,
108
- `Reasoning: ${state.reasoningEffort}`,
109
- `Approval: ${state.approvalMode}`,
110
- `Files: ${state.fileAccess}`,
111
- `Shell: ${state.allowShellCommands ? "enabled" : "disabled"}`,
112
- `Network: ${state.networkAccess ? "enabled" : "disabled"}`,
113
- `Pending approvals: ${state.pendingApprovals.length}`,
114
- "",
115
- `Received: ${body.message || "No message"}`
116
- ].join("\n");
117
-
118
- return sendJson(res, 200, {
119
- reply,
120
- session: state.sessionName,
121
- message: "desktop companion synced the live controller state",
122
- state: snapshot()
123
- });
124
- }
125
-
126
- sendJson(res, 404, { error: "not_found" });
127
- } catch (error) {
128
- sendJson(res, 500, {
129
- error: "internal_error",
130
- detail: error instanceof Error ? error.message : String(error)
131
- });
132
- }
133
- });
134
-
135
- server.listen(port, host, () => {
136
- console.log(`Codex desktop companion listening on http://${host}:${port}`);
137
- });
138
-
139
- function resolveHost(args) {
140
- const fromEnv = process.env.HOST?.trim();
141
- if (fromEnv) {
142
- return fromEnv;
143
- }
144
-
145
- const hostFlagIndex = args.findIndex((value) => value === "--host");
146
- if (hostFlagIndex >= 0 && args[hostFlagIndex + 1]) {
147
- return args[hostFlagIndex + 1];
148
- }
149
-
150
- return "127.0.0.1";
151
- }
152
-
153
- function snapshot() {
154
- return {
155
- status: state.status,
156
- desktopName: state.desktopName,
157
- sessionName: state.sessionName,
158
- workspacePath: state.workspacePath,
159
- model: state.model,
160
- reasoningEffort: state.reasoningEffort,
161
- approvalMode: state.approvalMode,
162
- fileAccess: state.fileAccess,
163
- allowShellCommands: state.allowShellCommands,
164
- networkAccess: state.networkAccess,
165
- syncDesktopTranscript: state.syncDesktopTranscript,
166
- activeTask: state.activeTask,
167
- lastAssistantReply: state.lastAssistantReply,
168
- lastUpdatedAt: state.lastUpdatedAt,
169
- pendingApprovals: state.pendingApprovals,
170
- openFiles: state.openFiles,
171
- terminalLines: state.terminalLines
172
- };
173
- }
174
-
175
- function applySettings(body) {
176
- state.desktopName = body.desktopName || state.desktopName;
177
- state.sessionName = body.sessionName || state.sessionName;
178
- state.workspacePath = body.workspacePath || state.workspacePath;
179
- state.model = body.model || state.model;
180
- state.reasoningEffort = body.reasoningEffort || state.reasoningEffort;
181
- state.approvalMode = body.approvalMode || state.approvalMode;
182
- state.fileAccess = body.fileAccess || state.fileAccess;
183
- state.allowShellCommands = body.allowShellCommands ?? state.allowShellCommands;
184
- state.networkAccess = body.networkAccess ?? state.networkAccess;
185
- state.syncDesktopTranscript = body.syncDesktopTranscript ?? state.syncDesktopTranscript;
186
- state.lastUpdatedAt = new Date().toISOString();
187
- }
188
-
189
- function applyAction(body) {
190
- const action = body.action || "refresh";
191
- const approvalId = body.approvalId || null;
192
-
193
- switch (action) {
194
- case "interrupt":
195
- state.status = "interrupted";
196
- state.activeTask = "Execution interrupted from iPhone.";
197
- state.lastAssistantReply = "Desktop task interrupted.";
198
- appendTerminal("warning", "Interrupt received from iPhone.");
199
- break;
200
- case "resume":
201
- state.status = "working";
202
- state.activeTask = "Execution resumed from iPhone.";
203
- state.lastAssistantReply = "Desktop task resumed.";
204
- appendTerminal("success", "Resume received from iPhone.");
205
- break;
206
- case "approve":
207
- removeApproval(approvalId);
208
- state.status = "working";
209
- state.activeTask = "Sensitive action approved from iPhone.";
210
- state.lastAssistantReply = "Approval granted.";
211
- appendTerminal("success", `Approved request ${approvalId || "unknown"}.`);
212
- break;
213
- case "reject":
214
- removeApproval(approvalId);
215
- state.status = "ready";
216
- state.activeTask = "Sensitive action rejected from iPhone.";
217
- state.lastAssistantReply = "Approval rejected.";
218
- appendTerminal("warning", `Rejected request ${approvalId || "unknown"}.`);
219
- break;
220
- default:
221
- state.lastAssistantReply = "Desktop state refreshed.";
222
- appendTerminal("info", "State refresh requested from iPhone.");
223
- break;
224
- }
225
-
226
- state.lastUpdatedAt = new Date().toISOString();
227
- return `desktop companion applied action: ${action}`;
228
- }
229
-
230
- function maybeQueueApproval(message) {
231
- if (!message) {
232
- return;
233
- }
234
-
235
- const lowered = String(message).toLowerCase();
236
- if (!/(delete|remove|install|registry|system32|powershell)/.test(lowered)) {
237
- return;
238
- }
239
-
240
- const id = `approval-${Date.now()}`;
241
- state.pendingApprovals.unshift({
242
- id,
243
- title: "Approve Sensitive Command",
244
- summary: "The desktop session wants to run a potentially sensitive command and is waiting for phone approval.",
245
- command: message,
246
- risk: "high"
247
- });
248
- state.pendingApprovals = state.pendingApprovals.slice(0, 4);
249
- appendTerminal("warning", `Queued approval ${id} for sensitive instruction.`);
250
- }
251
-
252
- function removeApproval(approvalId) {
253
- if (!approvalId) {
254
- return;
255
- }
256
- state.pendingApprovals = state.pendingApprovals.filter((approval) => approval.id !== approvalId);
257
- }
258
-
259
- function appendTerminal(level, text) {
260
- state.terminalLines.unshift(line(level, text));
261
- state.terminalLines = state.terminalLines.slice(0, 8);
262
- }
263
-
264
- function line(level, text) {
265
- return {
266
- id: `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`,
267
- level,
268
- text
269
- };
270
- }
271
-
272
- function sendJson(res, statusCode, body) {
273
- res.writeHead(statusCode, { "Content-Type": "application/json; charset=utf-8" });
274
- res.end(JSON.stringify(body, null, 2));
275
- }
276
-
277
- async function readJson(req) {
278
- const chunks = [];
279
-
280
- for await (const chunk of req) {
281
- chunks.push(chunk);
282
- }
283
-
284
- if (chunks.length === 0) {
285
- return {};
286
- }
287
-
288
- const raw = Buffer.concat(chunks).toString("utf8");
289
- return JSON.parse(raw);
290
- }