@cortexkit/opencode-openai-auth 0.7.2 → 0.9.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.
- package/README.md +9 -5
- package/dist/index-301y4qa1.js +2 -0
- package/dist/index-338z7171.js +211 -0
- package/dist/index-5y4vzdf8.js +2 -0
- package/dist/{index-zxqb5ydj.js → index-9ehhb051.js} +1 -1
- package/dist/{index-zg1x8sty.js → index-jwn4r3sw.js} +1 -1
- package/dist/{index-9jpc8yct.js → index-sdt2d2ra.js} +1 -1
- package/dist/index-w42s0g6m.js +2 -0
- package/dist/index.d.ts +213 -36
- package/dist/index.js +59 -154
- package/dist/internal-Y7QNVDJT.d.ts +908 -0
- package/dist/quota-normalize-3qffywcm.js +1 -0
- package/dist/rpc/port-file.d.ts +11 -9
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +2 -21
- package/dist/rpc/rpc-client.d.ts +7 -4
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.d.ts +7 -5
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/sidebar-state-B98sERYt.d.ts +219 -0
- package/dist/sidebar-state.d.ts +2 -171
- package/dist/sidebar-state.js +1 -1
- package/dist/{token-bvp0y166.js → token-9823y0pc.js} +1 -1
- package/dist/token-util-ypgz7rge.js +1 -0
- package/dist/tui-preferences.d.ts +27 -26
- package/dist/tui-preferences.js +1 -1
- package/dist/tui.d.ts +42 -19
- package/package.json +8 -14
- package/src/tui/entry.mjs +2 -2
- package/src/tui-compiled/{core/account-paths.ts → raw/core-account-paths.ts} +29 -18
- package/src/tui-compiled/raw/core-custody-state.ts +243 -0
- package/src/tui-compiled/raw/logger.ts +53 -0
- package/src/tui-compiled/{rpc/port-file.ts → raw/rpc-port-file.ts} +1 -1
- package/src/tui-compiled/raw/rpc-protocol.ts +12 -0
- package/src/{rpc/rpc-client.ts → tui-compiled/raw/rpc-rpc-client.ts} +2 -2
- package/src/{sidebar-state.ts → tui-compiled/raw/sidebar-state.ts} +142 -13
- package/src/{tui/command-dialogs.tsx → tui-compiled/raw/tui-command-dialogs.tsx} +94 -44
- package/src/{tui.tsx → tui-compiled/raw/tui.tsx} +149 -28
- package/src/{core/account-paths.ts → tui-compiled/runtime/core-account-paths.ts} +29 -18
- package/src/tui-compiled/runtime/core-custody-state.ts +243 -0
- package/src/tui-compiled/runtime/logger.ts +53 -0
- package/src/{rpc/port-file.ts → tui-compiled/runtime/rpc-port-file.ts} +1 -1
- package/src/tui-compiled/runtime/rpc-protocol.ts +12 -0
- package/src/tui-compiled/{rpc/rpc-client.ts → runtime/rpc-rpc-client.ts} +2 -2
- package/src/tui-compiled/{sidebar-state.ts → runtime/sidebar-state.ts} +142 -13
- package/src/tui-compiled/{tui/command-dialogs.tsx → runtime/tui-command-dialogs.tsx} +73 -37
- package/src/tui-compiled/{tui.tsx → runtime/tui.tsx} +251 -153
- package/src/tui-compiled/shared/internal.ts +6 -0
- package/src/{logger.ts → tui-compiled/shared/logger.ts} +91 -23
- package/src/tui-compiled/shared/paths.ts +33 -0
- package/src/{core → tui-compiled/shared}/refresh-file-lock.ts +7 -4
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -15
- package/dist/codex-http.d.ts +0 -3
- package/dist/commands.d.ts +0 -88
- package/dist/config.d.ts +0 -47
- package/dist/core/account-paths.d.ts +0 -25
- package/dist/core/accounts.d.ts +0 -330
- package/dist/core/atomic-write.d.ts +0 -1
- package/dist/core/background-quota-refresh.d.ts +0 -46
- package/dist/core/backoff.d.ts +0 -53
- package/dist/core/cachekeep.d.ts +0 -118
- package/dist/core/oauth.d.ts +0 -138
- package/dist/core/provider.d.ts +0 -70
- package/dist/core/quota-manager.d.ts +0 -192
- package/dist/core/refresh-all-quota.d.ts +0 -86
- package/dist/core/refresh-file-lock.d.ts +0 -12
- package/dist/core/reset-credits.d.ts +0 -116
- package/dist/core/sticky-routing.d.ts +0 -43
- package/dist/dump.d.ts +0 -20
- package/dist/hosted-web-search.d.ts +0 -5
- package/dist/index-87145jkw.js +0 -2
- package/dist/index-8f1200qx.js +0 -6
- package/dist/index-cfjed1st.js +0 -89
- package/dist/index-nrvjr97q.js +0 -3
- package/dist/index-qaggaze1.js +0 -2
- package/dist/index-sdcpzbnk.js +0 -2
- package/dist/logger.d.ts +0 -22
- package/dist/model-costs.d.ts +0 -29
- package/dist/prompt-context.d.ts +0 -19
- package/dist/quota-normalize-dvwtmy7f.js +0 -1
- package/dist/quota-normalize.d.ts +0 -43
- package/dist/raw-ws-bun.d.ts +0 -40
- package/dist/raw-ws-node.d.ts +0 -37
- package/dist/raw-ws-upgrade.d.ts +0 -2
- package/dist/raw-ws.d.ts +0 -3
- package/dist/response-stream-error.d.ts +0 -12
- package/dist/rpc/notifications.d.ts +0 -5
- package/dist/rpc/rpc-server.d.ts +0 -17
- package/dist/token-util-jcj7k7pa.js +0 -1
- package/dist/tui/command-dialogs.d.ts +0 -21
- package/dist/util/error.d.ts +0 -1
- package/dist/util/open-url.d.ts +0 -6
- package/dist/util/proxy-env.d.ts +0 -4
- package/dist/util/record.d.ts +0 -1
- package/dist/util/stable-json.d.ts +0 -1
- package/dist/util/uuid-v7.d.ts +0 -1
- package/dist/version.d.ts +0 -1
- package/dist/ws-pool.d.ts +0 -57
- package/dist/ws.d.ts +0 -71
- package/src/rpc/notifications.ts +0 -54
- package/src/rpc/protocol.ts +0 -33
- package/src/rpc/rpc-server.ts +0 -172
- package/src/tui-compiled/core/refresh-file-lock.ts +0 -381
- package/src/tui-compiled/logger.ts +0 -196
- package/src/tui-compiled/rpc/protocol.ts +0 -33
- package/src/util/error.ts +0 -9
- package/src/util/open-url.ts +0 -30
- package/src/util/proxy-env.ts +0 -42
- package/src/util/record.ts +0 -3
- package/src/util/stable-json.ts +0 -15
- package/src/util/uuid-v7.ts +0 -18
- /package/src/{rpc/rpc-dir.ts → tui-compiled/raw/rpc-rpc-dir.ts} +0 -0
- /package/src/tui-compiled/{tui-preferences.ts → raw/tui-preferences.ts} +0 -0
- /package/src/tui-compiled/{rpc/rpc-dir.ts → runtime/rpc-rpc-dir.ts} +0 -0
- /package/src/{tui-preferences.ts → tui-compiled/runtime/tui-preferences.ts} +0 -0
- /package/src/tui-compiled/{util → shared/util}/error.ts +0 -0
- /package/src/tui-compiled/{util → shared/util}/open-url.ts +0 -0
package/dist/ws.d.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { ResponseStreamError } from './response-stream-error';
|
|
2
|
-
export declare const PROTOCOL_HEADER = "responses_websockets=2026-02-06";
|
|
3
|
-
export interface ConnectResponsesWebSocketOptions {
|
|
4
|
-
url: string;
|
|
5
|
-
headers: Record<string, string>;
|
|
6
|
-
timeout?: number;
|
|
7
|
-
/** Use the hand-rolled raw TCP/TLS WebSocket client instead of native WebSocket. */
|
|
8
|
-
rawWebSocket?: boolean;
|
|
9
|
-
signal?: AbortSignal;
|
|
10
|
-
}
|
|
11
|
-
export interface StreamResponsesWebSocketOptions {
|
|
12
|
-
socket: WebSocket;
|
|
13
|
-
body: Record<string, unknown>;
|
|
14
|
-
sessionID?: string;
|
|
15
|
-
idleTimeout?: number;
|
|
16
|
-
signal?: AbortSignal;
|
|
17
|
-
onFirstEvent?: (error?: WrappedError) => void;
|
|
18
|
-
/**
|
|
19
|
-
* Fires on response.completed/response.done. `finalizedFunctionCallIds` is the
|
|
20
|
-
* set of function/custom tool call ids the response actually finalized (emitted
|
|
21
|
-
* a response.output_item.done for). The pool uses it to decide which suffix
|
|
22
|
-
* function_call items are safe to trim from a continuation: only those present
|
|
23
|
-
* in the chained response may be dropped — an unfinalized call (e.g. an aborted
|
|
24
|
-
* partial) must be kept inline or its function_call_output orphans → 400.
|
|
25
|
-
*/
|
|
26
|
-
onComplete?: (event: Record<string, unknown>, finalizedFunctionCallIds: Set<string>) => void;
|
|
27
|
-
onTerminal?: (event: Record<string, unknown>) => void;
|
|
28
|
-
onRetryableTerminal?: (event: Record<string, unknown>) => Promise<WebSocket | undefined>;
|
|
29
|
-
onConnectionInvalid?: (error: ResponseStreamError) => void;
|
|
30
|
-
onAbort?: (error: Error) => void;
|
|
31
|
-
/** Push per-turn quota from a codex.rate_limits in-band frame. */
|
|
32
|
-
onQuota?: (s: Record<string, unknown>) => void;
|
|
33
|
-
/** Called when the transport reports quota exhaustion for the current connection. */
|
|
34
|
-
onRateLimitReached?: (window: string, resetAt?: number) => void;
|
|
35
|
-
}
|
|
36
|
-
export interface WrappedError {
|
|
37
|
-
status: number;
|
|
38
|
-
headers?: Record<string, string>;
|
|
39
|
-
body: string;
|
|
40
|
-
}
|
|
41
|
-
export declare function toWebSocketUrl(url: string): string;
|
|
42
|
-
export declare function normalizeHeaders(headers: HeadersInit | undefined): Record<string, string>;
|
|
43
|
-
export declare function isAbortError(error: unknown): error is DOMException;
|
|
44
|
-
export declare function isUpgradeFailure(error: unknown): boolean;
|
|
45
|
-
export declare function isOversizedFrame(error: unknown): boolean;
|
|
46
|
-
export declare function markOversizedFrame<T extends object>(error: T): T;
|
|
47
|
-
export declare function connectResponsesWebSocket(options: ConnectResponsesWebSocketOptions): Promise<WebSocket>;
|
|
48
|
-
export declare function streamResponsesWebSocket(options: StreamResponsesWebSocketOptions): Response;
|
|
49
|
-
export declare function parseRateLimitSignal(value: unknown): {
|
|
50
|
-
window: string;
|
|
51
|
-
resetAt?: number;
|
|
52
|
-
} | undefined;
|
|
53
|
-
/**
|
|
54
|
-
* Surfaced when a stream dies after output has reached the reader.
|
|
55
|
-
*
|
|
56
|
-
* Must not contain any substring the host reads as retryable — no provider
|
|
57
|
-
* wording, no response ids, no byte counts. `ws-pool.test.ts` pins it against
|
|
58
|
-
* the host's pattern set.
|
|
59
|
-
*/
|
|
60
|
-
export declare const TERMINAL_AFTER_OUTPUT_MESSAGE = "The response ended early after part of it had already been shown. It was not sent again, because repeating it would duplicate that output and re-run any tools it had started. The transport log records what ended it.";
|
|
61
|
-
/**
|
|
62
|
-
* Surfaced when the peer refuses the request frame as too large (close 1009).
|
|
63
|
-
*
|
|
64
|
-
* Fixed text for the same reason as {@link TERMINAL_AFTER_OUTPUT_MESSAGE}: the
|
|
65
|
-
* host can override this error's non-retryable flag by matching the message,
|
|
66
|
-
* and resending a frame the peer has already measured and refused is the one
|
|
67
|
-
* outcome this path exists to prevent. The size and the peer's reason are
|
|
68
|
-
* logged instead.
|
|
69
|
-
*/
|
|
70
|
-
export declare const OVERSIZED_FRAME_MESSAGE = "The request was larger than the websocket would carry, so it was sent over HTTP instead. Resending it unchanged over the same socket cannot succeed. The transport log records the size.";
|
|
71
|
-
export * as OpenAIWebSocket from './ws';
|
package/src/rpc/notifications.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { OpenDialogPayload, RpcNotification } from './protocol'
|
|
2
|
-
|
|
3
|
-
const QUEUE_CAP = 100
|
|
4
|
-
const TUI_CONNECTED_WINDOW_MS = 3_000
|
|
5
|
-
|
|
6
|
-
let queue: RpcNotification[] = []
|
|
7
|
-
let nextId = 1
|
|
8
|
-
let lastDrainAtAny = 0
|
|
9
|
-
const lastDrainAtBySession = new Map<string, number>()
|
|
10
|
-
|
|
11
|
-
export function pushNotification(
|
|
12
|
-
payload: OpenDialogPayload,
|
|
13
|
-
sessionId?: string,
|
|
14
|
-
): void {
|
|
15
|
-
queue.push({ id: nextId++, type: 'open-dialog', payload, sessionId })
|
|
16
|
-
if (queue.length > QUEUE_CAP) queue = queue.slice(queue.length - QUEUE_CAP)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function drainNotifications(
|
|
20
|
-
lastReceivedId = 0,
|
|
21
|
-
sessionId?: string,
|
|
22
|
-
): RpcNotification[] {
|
|
23
|
-
const now = Date.now()
|
|
24
|
-
lastDrainAtAny = now
|
|
25
|
-
if (sessionId !== undefined) lastDrainAtBySession.set(sessionId, now)
|
|
26
|
-
const matches = (n: RpcNotification) =>
|
|
27
|
-
sessionId === undefined ||
|
|
28
|
-
n.sessionId === undefined ||
|
|
29
|
-
n.sessionId === sessionId
|
|
30
|
-
if (lastReceivedId > 0) {
|
|
31
|
-
queue = queue.filter((n) => {
|
|
32
|
-
if (n.id > lastReceivedId) return true
|
|
33
|
-
if (sessionId === undefined) return false
|
|
34
|
-
return n.sessionId !== sessionId
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
return queue.filter((n) => n.id > lastReceivedId && matches(n))
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function isTuiConnected(sessionId?: string): boolean {
|
|
41
|
-
const now = Date.now()
|
|
42
|
-
if (sessionId !== undefined) {
|
|
43
|
-
const at = lastDrainAtBySession.get(sessionId) ?? 0
|
|
44
|
-
return at > 0 && now - at < TUI_CONNECTED_WINDOW_MS
|
|
45
|
-
}
|
|
46
|
-
return lastDrainAtAny > 0 && now - lastDrainAtAny < TUI_CONNECTED_WINDOW_MS
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function resetNotificationsForTest(): void {
|
|
50
|
-
queue = []
|
|
51
|
-
nextId = 1
|
|
52
|
-
lastDrainAtAny = 0
|
|
53
|
-
lastDrainAtBySession.clear()
|
|
54
|
-
}
|
package/src/rpc/protocol.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export type CommandModalName =
|
|
2
|
-
| 'openai-quota'
|
|
3
|
-
| 'openai-account'
|
|
4
|
-
| 'openai-routing'
|
|
5
|
-
| 'openai-killswitch'
|
|
6
|
-
| 'openai-dump'
|
|
7
|
-
| 'openai-logging'
|
|
8
|
-
| 'openai-cachekeep'
|
|
9
|
-
| 'openai-reset'
|
|
10
|
-
|
|
11
|
-
export interface OpenDialogPayload {
|
|
12
|
-
command: CommandModalName
|
|
13
|
-
text: string
|
|
14
|
-
knobs: Record<string, unknown>
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface RpcNotification {
|
|
18
|
-
id: number
|
|
19
|
-
type: 'open-dialog'
|
|
20
|
-
payload: OpenDialogPayload
|
|
21
|
-
sessionId?: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface ApplyRequest {
|
|
25
|
-
command: CommandModalName
|
|
26
|
-
arguments: string
|
|
27
|
-
sessionId?: string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface ApplyResult {
|
|
31
|
-
text: string
|
|
32
|
-
knobs: Record<string, unknown>
|
|
33
|
-
}
|
package/src/rpc/rpc-server.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { randomBytes, timingSafeEqual } from 'node:crypto'
|
|
2
|
-
import { unlink } from 'node:fs/promises'
|
|
3
|
-
import {
|
|
4
|
-
createServer,
|
|
5
|
-
type IncomingMessage,
|
|
6
|
-
type ServerResponse,
|
|
7
|
-
} from 'node:http'
|
|
8
|
-
import { join } from 'node:path'
|
|
9
|
-
import { createLogger } from '../logger'
|
|
10
|
-
import type { drainNotifications } from './notifications'
|
|
11
|
-
import { sweepRpcState, writePortFile } from './port-file'
|
|
12
|
-
import type { ApplyRequest, ApplyResult } from './protocol'
|
|
13
|
-
|
|
14
|
-
const log = createLogger('rpc')
|
|
15
|
-
|
|
16
|
-
export interface RpcServerHandle {
|
|
17
|
-
port: number
|
|
18
|
-
token: string
|
|
19
|
-
stop: () => Promise<void>
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface RpcServerOptions {
|
|
23
|
-
dir: string
|
|
24
|
-
secureDir?: boolean
|
|
25
|
-
sweepRoot?: string
|
|
26
|
-
drain: typeof drainNotifications
|
|
27
|
-
apply: (request: ApplyRequest) => Promise<ApplyResult>
|
|
28
|
-
// Bounds handler execution via the socket inactivity timer.
|
|
29
|
-
timeoutMs?: number
|
|
30
|
-
// Bounds request delivery only (requestTimeout/headersTimeout).
|
|
31
|
-
receiptTimeoutMs?: number
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function readBody(req: IncomingMessage): Promise<string> {
|
|
35
|
-
return new Promise((resolve, reject) => {
|
|
36
|
-
const chunks: Buffer[] = []
|
|
37
|
-
let size = 0
|
|
38
|
-
req.on('data', (chunk: Buffer) => {
|
|
39
|
-
size += chunk.length
|
|
40
|
-
if (size > 1_000_000) {
|
|
41
|
-
req.destroy()
|
|
42
|
-
reject(new Error('body too large'))
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
chunks.push(chunk)
|
|
46
|
-
})
|
|
47
|
-
req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))
|
|
48
|
-
req.on('error', reject)
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function tokenOk(header: string | undefined, token: string): boolean {
|
|
53
|
-
if (!header?.startsWith('Bearer ')) return false
|
|
54
|
-
const got = Buffer.from(header.slice(7))
|
|
55
|
-
const want = Buffer.from(token)
|
|
56
|
-
return got.length === want.length && timingSafeEqual(got, want)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export async function startRpcServer(
|
|
60
|
-
options: RpcServerOptions,
|
|
61
|
-
): Promise<RpcServerHandle> {
|
|
62
|
-
const token = randomBytes(32).toString('hex')
|
|
63
|
-
// Two different bounds, deliberately not one value.
|
|
64
|
-
//
|
|
65
|
-
// requestTimeout/headersTimeout bound how long a client may take to DELIVER
|
|
66
|
-
// a request; they do not bound handler execution. A receipt bound of 500ms
|
|
67
|
-
// still returns 200 for a 3s handler. Over loopback with a 1 MiB body cap,
|
|
68
|
-
// seconds is already generous.
|
|
69
|
-
//
|
|
70
|
-
// The inactivity timer is the one that can kill a working handler: it
|
|
71
|
-
// destroys the socket out from under it. It must therefore outlast the
|
|
72
|
-
// slowest legitimate apply — a reset redemption is bounded by a 60s consume
|
|
73
|
-
// call — or the response is lost server-side no matter what deadline the
|
|
74
|
-
// client passed. Fast commands respond in milliseconds regardless.
|
|
75
|
-
//
|
|
76
|
-
// Collapsing these back into a single value reintroduces one of two bugs:
|
|
77
|
-
// a receipt bound that aborts a slow reset, or a socket timer that leaves
|
|
78
|
-
// every endpoint holding a dead connection for 90s.
|
|
79
|
-
const handlerTimeoutMs = options.timeoutMs ?? 90_000
|
|
80
|
-
const receiptTimeoutMs = options.receiptTimeoutMs ?? 2_000
|
|
81
|
-
const server = createServer((req, res) => {
|
|
82
|
-
req.setTimeout(handlerTimeoutMs, () => {
|
|
83
|
-
req.socket.destroy()
|
|
84
|
-
})
|
|
85
|
-
void dispatch(req, res)
|
|
86
|
-
})
|
|
87
|
-
server.requestTimeout = receiptTimeoutMs
|
|
88
|
-
server.headersTimeout = receiptTimeoutMs
|
|
89
|
-
|
|
90
|
-
async function dispatch(req: IncomingMessage, res: ServerResponse) {
|
|
91
|
-
const json = (status: number, value: unknown) => {
|
|
92
|
-
// Guard against writing to a socket that was destroyed (e.g. when
|
|
93
|
-
// readBody rejected after req.destroy() on an oversized body).
|
|
94
|
-
if (res.headersSent || res.writableEnded || res.destroyed) return
|
|
95
|
-
res.writeHead(status, { 'content-type': 'application/json' })
|
|
96
|
-
res.end(JSON.stringify(value))
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
const url = req.url ?? ''
|
|
100
|
-
if (req.method === 'GET' && url === '/health')
|
|
101
|
-
return json(200, { ok: true })
|
|
102
|
-
if (req.method !== 'POST' || !url.startsWith('/rpc/'))
|
|
103
|
-
return json(404, { error: 'not found' })
|
|
104
|
-
if (!tokenOk(req.headers.authorization, token))
|
|
105
|
-
return json(401, { error: 'unauthorized' })
|
|
106
|
-
const method = url.slice('/rpc/'.length)
|
|
107
|
-
const body = await readBody(req)
|
|
108
|
-
const params = JSON.parse(body || '{}') as Record<string, unknown>
|
|
109
|
-
if (method === 'pending-notifications') {
|
|
110
|
-
const messages = options.drain(
|
|
111
|
-
Number(params.lastReceivedId ?? 0),
|
|
112
|
-
typeof params.sessionId === 'string' ? params.sessionId : undefined,
|
|
113
|
-
)
|
|
114
|
-
return json(200, { messages })
|
|
115
|
-
}
|
|
116
|
-
if (method === 'apply') {
|
|
117
|
-
const result = await options.apply(params as unknown as ApplyRequest)
|
|
118
|
-
return json(200, result)
|
|
119
|
-
}
|
|
120
|
-
return json(404, { error: 'unknown method' })
|
|
121
|
-
} catch (error) {
|
|
122
|
-
json(500, {
|
|
123
|
-
error: error instanceof Error ? error.message : String(error),
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const port = await new Promise<number>((resolve, reject) => {
|
|
129
|
-
server.on('error', reject)
|
|
130
|
-
server.listen(0, '127.0.0.1', () => {
|
|
131
|
-
const addr = server.address()
|
|
132
|
-
if (addr && typeof addr === 'object') resolve(addr.port)
|
|
133
|
-
else reject(new Error('no port'))
|
|
134
|
-
})
|
|
135
|
-
})
|
|
136
|
-
server.unref()
|
|
137
|
-
if (options.sweepRoot) {
|
|
138
|
-
try {
|
|
139
|
-
await sweepRpcState(options.sweepRoot, options.dir)
|
|
140
|
-
} catch (error) {
|
|
141
|
-
log.warn('rpc state sweep failed', {
|
|
142
|
-
pid: process.pid,
|
|
143
|
-
error: error instanceof Error ? error.message : String(error),
|
|
144
|
-
})
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
try {
|
|
148
|
-
await writePortFile(
|
|
149
|
-
options.dir,
|
|
150
|
-
{ port, token, pid: process.pid },
|
|
151
|
-
{ secureDir: options.secureDir },
|
|
152
|
-
)
|
|
153
|
-
log.debug('rpc server pid', {
|
|
154
|
-
pid: process.pid,
|
|
155
|
-
rpcPort: port,
|
|
156
|
-
})
|
|
157
|
-
} catch (error) {
|
|
158
|
-
await new Promise<void>((resolve) => server.close(() => resolve()))
|
|
159
|
-
throw error
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
port,
|
|
164
|
-
token,
|
|
165
|
-
async stop() {
|
|
166
|
-
await new Promise<void>((resolve) => server.close(() => resolve()))
|
|
167
|
-
await unlink(join(options.dir, `port-${process.pid}.json`)).catch(
|
|
168
|
-
() => {},
|
|
169
|
-
)
|
|
170
|
-
},
|
|
171
|
-
}
|
|
172
|
-
}
|