agent-shim 8.24.0 → 8.26.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/dist/cli.cjs +713 -259
- package/dist/index.cjs +468 -113
- package/dist/index.mjs +460 -113
- package/dist/types/index.d.ts +310 -6
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -61796,7 +61796,7 @@ function registerIdentityCommand(program2, deps) {
|
|
|
61796
61796
|
// package.json
|
|
61797
61797
|
var package_default = {
|
|
61798
61798
|
name: "agent-shim",
|
|
61799
|
-
version: "8.
|
|
61799
|
+
version: "8.26.0",
|
|
61800
61800
|
description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
61801
61801
|
license: "MIT",
|
|
61802
61802
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -66142,13 +66142,6 @@ var https3 = __toESM(require("node:https"), 1);
|
|
|
66142
66142
|
var net2 = __toESM(require("node:net"), 1);
|
|
66143
66143
|
var tls = __toESM(require("node:tls"), 1);
|
|
66144
66144
|
|
|
66145
|
-
// src/frontdoor/server.ts
|
|
66146
|
-
var import_node_http2 = __toESM(require("node:http"), 1);
|
|
66147
|
-
var import_node_https = __toESM(require("node:https"), 1);
|
|
66148
|
-
|
|
66149
|
-
// src/frontdoor/rcControl.ts
|
|
66150
|
-
var https = __toESM(require("node:https"), 1);
|
|
66151
|
-
|
|
66152
66145
|
// src/frontdoor/rcSessions.ts
|
|
66153
66146
|
var RC_SESSIONS_PATH_PREFIX = "/v1/code/sessions";
|
|
66154
66147
|
var RC_SESSION_ID_PREFIX = "cse_";
|
|
@@ -66725,7 +66718,7 @@ async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
|
66725
66718
|
}
|
|
66726
66719
|
return result;
|
|
66727
66720
|
}
|
|
66728
|
-
async function deliverRcClientPayload(deps, sessionId, payload, action) {
|
|
66721
|
+
async function deliverRcClientPayload(deps, sessionId, payload, action, to = "events") {
|
|
66729
66722
|
const credential = deps.credentialOf(sessionId);
|
|
66730
66723
|
if (credential === void 0) {
|
|
66731
66724
|
return { ok: false, message: rcSessionNotObservedMessage(sessionId) };
|
|
@@ -66736,7 +66729,7 @@ async function deliverRcClientPayload(deps, sessionId, payload, action) {
|
|
|
66736
66729
|
const body = JSON.stringify(buildRcEventWriteBody(payload));
|
|
66737
66730
|
let answer;
|
|
66738
66731
|
try {
|
|
66739
|
-
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
66732
|
+
answer = await (to === "teleport-events" ? deps.dial.writeTeleportEvents(sessionId, rcWriteHeaders(credential), body) : deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body));
|
|
66740
66733
|
} catch (error62) {
|
|
66741
66734
|
return { ok: false, message: `the door could not reach the API host to ${action}: ${error62 instanceof Error ? error62.message : String(error62)}` };
|
|
66742
66735
|
}
|
|
@@ -66830,8 +66823,22 @@ async function submitRcSessionMcpOAuthCallbackUrl(deps, sessionId, serverName, c
|
|
|
66830
66823
|
async function sendRcKeepAlive(deps, sessionId) {
|
|
66831
66824
|
return await deliverRcClientPayload(deps, sessionId, buildRcKeepAlivePayload(), `keep session ${sessionId} alive`);
|
|
66832
66825
|
}
|
|
66826
|
+
async function teleportRcSession(deps, sessionId, marker) {
|
|
66827
|
+
if (marker === "") {
|
|
66828
|
+
return { ok: false, message: "a teleport write needs a non-empty marker: the teleport relay anchors on a marker line's uuid and string content, and an empty string carries neither" };
|
|
66829
|
+
}
|
|
66830
|
+
return await deliverRcClientPayload(deps, sessionId, buildRcUserMessagePayload(deps.newUuid(), sessionId, marker), `teleport a marker into session ${sessionId}`, "teleport-events");
|
|
66831
|
+
}
|
|
66832
|
+
function buildRcMarkReadBody(eventId) {
|
|
66833
|
+
return eventId === void 0 ? {} : { event_id: eventId };
|
|
66834
|
+
}
|
|
66835
|
+
|
|
66836
|
+
// src/frontdoor/server.ts
|
|
66837
|
+
var import_node_http2 = __toESM(require("node:http"), 1);
|
|
66838
|
+
var import_node_https = __toESM(require("node:https"), 1);
|
|
66833
66839
|
|
|
66834
66840
|
// src/frontdoor/rcControl.ts
|
|
66841
|
+
var https = __toESM(require("node:https"), 1);
|
|
66835
66842
|
var RC_PERMISSION_MODE_LIST = RC_PERMISSION_MODES.join(", ");
|
|
66836
66843
|
var CONTROL_PATH_PREFIX = "/__agent-shim/rc";
|
|
66837
66844
|
var CONTROL_BODY_CAP_BYTES = 10485760;
|
|
@@ -67005,6 +67012,15 @@ function createRcControlHandler(deps) {
|
|
|
67005
67012
|
const callbackUrl = bodyString(body, "callbackUrl");
|
|
67006
67013
|
return session === void 0 || serverName === void 0 || callbackUrl === void 0 ? { error: "the mcp-oauth-callback-url body must be JSON naming a non-empty session id, server name, and callback URL" } : { session, run: async () => await deps.mcpOAuthCallbackUrl(session, serverName, callbackUrl) };
|
|
67007
67014
|
}
|
|
67015
|
+
},
|
|
67016
|
+
{
|
|
67017
|
+
name: "teleport",
|
|
67018
|
+
path: "teleport",
|
|
67019
|
+
read: (body) => {
|
|
67020
|
+
const session = bodyString(body, "session");
|
|
67021
|
+
const marker = bodyString(body, "marker");
|
|
67022
|
+
return session === void 0 || marker === void 0 ? { error: "the teleport body must be JSON naming a non-empty session id and marker" } : { session, run: async () => await deps.teleport(session, marker) };
|
|
67023
|
+
}
|
|
67008
67024
|
}
|
|
67009
67025
|
];
|
|
67010
67026
|
return (request7, response) => {
|
|
@@ -67368,7 +67384,8 @@ function frontDoorRcControl(transport, token) {
|
|
|
67368
67384
|
mcpStatus: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-status`, JSON.stringify({ session: sessionId }), (status, message) => `requesting the MCP status of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
67369
67385
|
mcpReconnect: async (sessionId, serverName) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-reconnect`, JSON.stringify({ session: sessionId, serverName }), (status, message) => `reconnecting MCP server ${serverName} on ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
67370
67386
|
mcpAuthenticate: async (sessionId, serverName, redirectUri) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-authenticate`, JSON.stringify({ session: sessionId, serverName, redirectUri }), (status, message) => `authenticating MCP server ${serverName} on ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
67371
|
-
mcpOAuthCallbackUrl: async (sessionId, serverName, callbackUrl) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-oauth-callback-url`, JSON.stringify({ session: sessionId, serverName, callbackUrl }), (status, message) => `handing MCP server ${serverName}'s OAuth callback to ${sessionId} failed (HTTP ${String(status)}): ${message}`)
|
|
67387
|
+
mcpOAuthCallbackUrl: async (sessionId, serverName, callbackUrl) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-oauth-callback-url`, JSON.stringify({ session: sessionId, serverName, callbackUrl }), (status, message) => `handing MCP server ${serverName}'s OAuth callback to ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
67388
|
+
teleport: async (sessionId, marker) => await writeOf(`${CONTROL_PATH_PREFIX}/teleport`, JSON.stringify({ session: sessionId, marker }), (status, message) => `teleporting a marker into ${sessionId} failed (HTTP ${String(status)}): ${message}`)
|
|
67372
67389
|
};
|
|
67373
67390
|
}
|
|
67374
67391
|
|
|
@@ -67650,36 +67667,38 @@ function tlsFacts(options) {
|
|
|
67650
67667
|
}
|
|
67651
67668
|
function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
67652
67669
|
const agent = new ExemptTlsAgent();
|
|
67653
|
-
|
|
67654
|
-
|
|
67655
|
-
|
|
67656
|
-
|
|
67657
|
-
|
|
67658
|
-
|
|
67659
|
-
|
|
67660
|
-
|
|
67661
|
-
|
|
67662
|
-
|
|
67663
|
-
|
|
67664
|
-
|
|
67665
|
-
|
|
67666
|
-
|
|
67667
|
-
|
|
67668
|
-
|
|
67669
|
-
|
|
67670
|
-
|
|
67671
|
-
const
|
|
67672
|
-
|
|
67673
|
-
|
|
67674
|
-
chunks.push(chunk);
|
|
67675
|
-
});
|
|
67676
|
-
response.on("end", () => {
|
|
67677
|
-
resolve({ status: response.statusCode ?? HTTP_BAD_GATEWAY, body: Buffer.concat(chunks).toString("utf8") });
|
|
67678
|
-
});
|
|
67670
|
+
const post = async (path46, headers, body) => await new Promise((resolve, reject) => {
|
|
67671
|
+
const options = {
|
|
67672
|
+
host: target.host,
|
|
67673
|
+
port: target.port,
|
|
67674
|
+
method: "POST",
|
|
67675
|
+
path: path46,
|
|
67676
|
+
// The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
|
|
67677
|
+
headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
|
|
67678
|
+
agent
|
|
67679
|
+
};
|
|
67680
|
+
options.servername = target.servername ?? target.host;
|
|
67681
|
+
if (target.ca !== void 0) {
|
|
67682
|
+
options.ca = [...target.ca];
|
|
67683
|
+
}
|
|
67684
|
+
if (target.rejectUnauthorized !== void 0) {
|
|
67685
|
+
options.rejectUnauthorized = target.rejectUnauthorized;
|
|
67686
|
+
}
|
|
67687
|
+
const request7 = https3.request(options, (response) => {
|
|
67688
|
+
const chunks = [];
|
|
67689
|
+
response.on("data", (chunk) => {
|
|
67690
|
+
chunks.push(chunk);
|
|
67679
67691
|
});
|
|
67680
|
-
|
|
67681
|
-
|
|
67682
|
-
|
|
67692
|
+
response.on("end", () => {
|
|
67693
|
+
resolve({ status: response.statusCode ?? HTTP_BAD_GATEWAY, body: Buffer.concat(chunks).toString("utf8") });
|
|
67694
|
+
});
|
|
67695
|
+
});
|
|
67696
|
+
request7.once("error", reject);
|
|
67697
|
+
request7.end(body);
|
|
67698
|
+
});
|
|
67699
|
+
return {
|
|
67700
|
+
writeEvents: async (sessionId, headers, body) => await post(`/v1/code/sessions/${encodeURIComponent(sessionId)}/events`, headers, body),
|
|
67701
|
+
writeTeleportEvents: async (sessionId, headers, body) => await post(`/v1/code/sessions/${encodeURIComponent(sessionId)}/teleport-events`, headers, body)
|
|
67683
67702
|
};
|
|
67684
67703
|
}
|
|
67685
67704
|
var NO_CHUNKS = {
|
|
@@ -67697,7 +67716,8 @@ function lateRcEventDial(resolve) {
|
|
|
67697
67716
|
return built.dial;
|
|
67698
67717
|
};
|
|
67699
67718
|
return {
|
|
67700
|
-
writeEvents: async (sessionId, headers, body) => await dialFor().writeEvents(sessionId, headers, body)
|
|
67719
|
+
writeEvents: async (sessionId, headers, body) => await dialFor().writeEvents(sessionId, headers, body),
|
|
67720
|
+
writeTeleportEvents: async (sessionId, headers, body) => await dialFor().writeTeleportEvents(sessionId, headers, body)
|
|
67701
67721
|
};
|
|
67702
67722
|
}
|
|
67703
67723
|
function lateRcStreamDial(resolve) {
|
|
@@ -67710,7 +67730,8 @@ function lateRcStreamDial(resolve) {
|
|
|
67710
67730
|
return built.dial;
|
|
67711
67731
|
};
|
|
67712
67732
|
return {
|
|
67713
|
-
announcePresence: async (sessionId, headers, clientId) => await dialFor().announcePresence(sessionId, headers, clientId),
|
|
67733
|
+
announcePresence: async (sessionId, headers, clientId, clear) => await dialFor().announcePresence(sessionId, headers, clientId, clear),
|
|
67734
|
+
markRead: async (sessionId, headers, eventId) => await dialFor().markRead(sessionId, headers, eventId),
|
|
67714
67735
|
openStream: async (sessionId, headers, resume, signal) => await dialFor().openStream(sessionId, headers, resume, signal)
|
|
67715
67736
|
};
|
|
67716
67737
|
}
|
|
@@ -67752,11 +67773,16 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
67752
67773
|
return Buffer.concat(chunks).toString("utf8");
|
|
67753
67774
|
};
|
|
67754
67775
|
return {
|
|
67755
|
-
announcePresence: async (sessionId, headers, clientId) => {
|
|
67756
|
-
const body = JSON.stringify({ client_id: clientId, clear
|
|
67776
|
+
announcePresence: async (sessionId, headers, clientId, clear) => {
|
|
67777
|
+
const body = JSON.stringify({ client_id: clientId, clear });
|
|
67757
67778
|
const { status, response } = await request7("POST", `/v1/code/sessions/${encodeURIComponent(sessionId)}/client/presence`, { ...headers, "content-type": "application/json" }, body, new AbortController().signal);
|
|
67758
67779
|
return { status, body: await readAll(response) };
|
|
67759
67780
|
},
|
|
67781
|
+
markRead: async (sessionId, headers, eventId) => {
|
|
67782
|
+
const body = JSON.stringify(buildRcMarkReadBody(eventId));
|
|
67783
|
+
const { status, response } = await request7("POST", `/v1/code/sessions/${encodeURIComponent(sessionId)}/mark_read`, { ...headers, "content-type": "application/json" }, body, new AbortController().signal);
|
|
67784
|
+
return { status, body: await readAll(response) };
|
|
67785
|
+
},
|
|
67760
67786
|
openStream: async (sessionId, headers, resume, signal) => {
|
|
67761
67787
|
const path46 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
|
|
67762
67788
|
const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
|
|
@@ -69640,6 +69666,166 @@ var CheckReportJsonSchema = external_exports.strictObject({
|
|
|
69640
69666
|
|
|
69641
69667
|
// src/frontdoor/controlSchemas.ts
|
|
69642
69668
|
var import_node_path33 = __toESM(require("node:path"), 1);
|
|
69669
|
+
|
|
69670
|
+
// src/frontdoor/rcSchemas.ts
|
|
69671
|
+
var RcPermissionModeSchema = external_exports.enum(RC_PERMISSION_MODES);
|
|
69672
|
+
var RcSessionSummarySchema = external_exports.strictObject({
|
|
69673
|
+
id: external_exports.string(),
|
|
69674
|
+
createdAt: external_exports.number(),
|
|
69675
|
+
lastSeenAt: external_exports.number()
|
|
69676
|
+
});
|
|
69677
|
+
function workerFactSchema(value2) {
|
|
69678
|
+
return external_exports.strictObject({ value: value2, observedAt: external_exports.number() });
|
|
69679
|
+
}
|
|
69680
|
+
var RcPendingRequestSummarySchema = external_exports.strictObject({
|
|
69681
|
+
sessionId: external_exports.string(),
|
|
69682
|
+
requestId: external_exports.string(),
|
|
69683
|
+
type: external_exports.string(),
|
|
69684
|
+
summary: external_exports.string(),
|
|
69685
|
+
observedAt: external_exports.number()
|
|
69686
|
+
});
|
|
69687
|
+
var RcSessionStatusSchema = external_exports.strictObject({
|
|
69688
|
+
...RcSessionSummarySchema.shape,
|
|
69689
|
+
workerState: workerFactSchema(external_exports.string()).optional(),
|
|
69690
|
+
workerIdleSeconds: workerFactSchema(external_exports.number()).optional(),
|
|
69691
|
+
pending: external_exports.readonly(external_exports.array(RcPendingRequestSummarySchema))
|
|
69692
|
+
});
|
|
69693
|
+
var RcStreamEnvelopeSchema = external_exports.looseObject({
|
|
69694
|
+
/** The envelope's own event id, when the host sent one. */
|
|
69695
|
+
event_id: external_exports.string().optional(),
|
|
69696
|
+
/** The envelope's event type, the discriminator a consumer switches on (`control_request`, `user`, and kin). */
|
|
69697
|
+
event_type: external_exports.string(),
|
|
69698
|
+
/** The sequence number the host assigned, the value a resume continues after. */
|
|
69699
|
+
sequence_num: external_exports.int(),
|
|
69700
|
+
/** Who emitted the event (`worker` for the CLI's half, a client id for a client's). */
|
|
69701
|
+
source: external_exports.string(),
|
|
69702
|
+
/** The event's payload, carried verbatim: its shape is the payload family's, narrowed by whichever consumer needs it. Optional in the schema's own type because the door forwards the host's envelope as it arrived, asserting only the fields it relies on itself. */
|
|
69703
|
+
payload: external_exports.unknown().optional(),
|
|
69704
|
+
/** When the host created the event; the protocol's own type for this field is not established here, so it is forwarded rather than asserted. */
|
|
69705
|
+
created_at: external_exports.unknown().optional()
|
|
69706
|
+
});
|
|
69707
|
+
var RcStreamEventSchema = external_exports.strictObject({
|
|
69708
|
+
session: external_exports.string(),
|
|
69709
|
+
envelope: RcStreamEnvelopeSchema
|
|
69710
|
+
});
|
|
69711
|
+
var RcRateLimitWindowSchema = external_exports.looseObject({
|
|
69712
|
+
/** The fraction of the window used, usually between 0 and 1, above 1 when usage legitimately runs past the window's cap (the CLI's own field description states both). */
|
|
69713
|
+
utilization: external_exports.number().optional(),
|
|
69714
|
+
/** When the window resets, in unix epoch seconds: the unit is the CLI's own field description, stated in the 2.1.289 bundle's schema. */
|
|
69715
|
+
resetsAt: external_exports.number().optional()
|
|
69716
|
+
});
|
|
69717
|
+
var RcRateLimitInfoSchema = external_exports.looseObject({
|
|
69718
|
+
/** The limiting window's own status (`allowed`, `allowed_warning`, `rejected`), asserted only as a string because the vocabulary grows with the CLI. */
|
|
69719
|
+
status: external_exports.string(),
|
|
69720
|
+
/** When the limiting window resets, in unix epoch seconds. */
|
|
69721
|
+
resetsAt: external_exports.number().optional(),
|
|
69722
|
+
/** Which window the top-level fields describe (`five_hour`, `seven_day`, and kin), the payload's own name for it. */
|
|
69723
|
+
rateLimitType: external_exports.string().optional(),
|
|
69724
|
+
/** The fraction of the limiting window used, on the same scale the per-window utilizations carry. */
|
|
69725
|
+
utilization: external_exports.number().optional(),
|
|
69726
|
+
/** Whether usage beyond the plan (extra usage) is currently covering the overflow, the payload's own flag for it. */
|
|
69727
|
+
isUsingOverage: external_exports.boolean().optional(),
|
|
69728
|
+
/** The overage's own status, the same vocabulary the limiting window's `status` carries. */
|
|
69729
|
+
overageStatus: external_exports.string().optional(),
|
|
69730
|
+
/** When the overage window resets, in unix epoch seconds. */
|
|
69731
|
+
overageResetsAt: external_exports.number().optional(),
|
|
69732
|
+
/** Each subscription window the account's response headers carried: the session (five-hour), weekly (seven-day), and overage-included weekly windows, each present only when the account's responses carry it. */
|
|
69733
|
+
unifiedWindows: external_exports.looseObject({ five_hour: RcRateLimitWindowSchema.optional(), seven_day: RcRateLimitWindowSchema.optional(), seven_day_overage_included: RcRateLimitWindowSchema.optional() }).optional()
|
|
69734
|
+
});
|
|
69735
|
+
var RcLiveRateLimitSchema = external_exports.strictObject({
|
|
69736
|
+
session: external_exports.string(),
|
|
69737
|
+
observedAt: external_exports.number(),
|
|
69738
|
+
rateLimit: RcRateLimitInfoSchema
|
|
69739
|
+
});
|
|
69740
|
+
var RcSessionQuerySchema = external_exports.strictObject({
|
|
69741
|
+
session: external_exports.string().min(1).optional()
|
|
69742
|
+
});
|
|
69743
|
+
var RcSendInputSchema = external_exports.strictObject({
|
|
69744
|
+
session: external_exports.string().min(1),
|
|
69745
|
+
text: external_exports.string().min(1)
|
|
69746
|
+
});
|
|
69747
|
+
var RcAnswerInputSchema = external_exports.strictObject({
|
|
69748
|
+
session: external_exports.string().min(1),
|
|
69749
|
+
request: external_exports.string().min(1),
|
|
69750
|
+
approve: external_exports.boolean(),
|
|
69751
|
+
text: external_exports.string().optional()
|
|
69752
|
+
}).refine((input2) => !input2.approve || input2.text === void 0 || input2.text === "", { message: "an approval carries no text (the protocol's allow result has no message field); text is the denial message" });
|
|
69753
|
+
var RcInterruptInputSchema = external_exports.strictObject({
|
|
69754
|
+
session: external_exports.string().min(1)
|
|
69755
|
+
});
|
|
69756
|
+
var RcSetModelInputSchema = external_exports.strictObject({
|
|
69757
|
+
session: external_exports.string().min(1),
|
|
69758
|
+
model: external_exports.string().min(1)
|
|
69759
|
+
});
|
|
69760
|
+
var RcSetPermissionModeInputSchema = external_exports.strictObject({
|
|
69761
|
+
session: external_exports.string().min(1),
|
|
69762
|
+
mode: RcPermissionModeSchema
|
|
69763
|
+
});
|
|
69764
|
+
var RcEndSessionInputSchema = external_exports.strictObject({
|
|
69765
|
+
session: external_exports.string().min(1),
|
|
69766
|
+
reason: external_exports.string().min(1).optional()
|
|
69767
|
+
});
|
|
69768
|
+
var RcGetUsageInputSchema = external_exports.strictObject({
|
|
69769
|
+
session: external_exports.string().min(1),
|
|
69770
|
+
skipBehaviors: external_exports.boolean().optional()
|
|
69771
|
+
});
|
|
69772
|
+
var RcGetContextUsageInputSchema = external_exports.strictObject({
|
|
69773
|
+
session: external_exports.string().min(1),
|
|
69774
|
+
detail: external_exports.enum(RC_CONTEXT_USAGE_DETAILS).optional()
|
|
69775
|
+
});
|
|
69776
|
+
var RcReadFileInputSchema = external_exports.strictObject({
|
|
69777
|
+
session: external_exports.string().min(1),
|
|
69778
|
+
path: external_exports.string().min(1),
|
|
69779
|
+
maxBytes: external_exports.number().int().positive().optional(),
|
|
69780
|
+
encoding: external_exports.enum(RC_READ_FILE_ENCODINGS).optional()
|
|
69781
|
+
});
|
|
69782
|
+
var RcFileSuggestionsInputSchema = external_exports.strictObject({
|
|
69783
|
+
session: external_exports.string().min(1),
|
|
69784
|
+
query: external_exports.string()
|
|
69785
|
+
});
|
|
69786
|
+
var RcKeepAliveInputSchema = external_exports.strictObject({
|
|
69787
|
+
session: external_exports.string().min(1)
|
|
69788
|
+
});
|
|
69789
|
+
var RcMcpStatusInputSchema = external_exports.strictObject({
|
|
69790
|
+
session: external_exports.string().min(1)
|
|
69791
|
+
});
|
|
69792
|
+
var RcMcpReconnectInputSchema = external_exports.strictObject({
|
|
69793
|
+
session: external_exports.string().min(1),
|
|
69794
|
+
serverName: external_exports.string().min(1)
|
|
69795
|
+
});
|
|
69796
|
+
var RcMcpAuthenticateInputSchema = external_exports.strictObject({
|
|
69797
|
+
session: external_exports.string().min(1),
|
|
69798
|
+
serverName: external_exports.string().min(1),
|
|
69799
|
+
redirectUri: external_exports.string().min(1)
|
|
69800
|
+
});
|
|
69801
|
+
var RcMcpOAuthCallbackUrlInputSchema = external_exports.strictObject({
|
|
69802
|
+
session: external_exports.string().min(1),
|
|
69803
|
+
serverName: external_exports.string().min(1),
|
|
69804
|
+
callbackUrl: external_exports.string().min(1)
|
|
69805
|
+
});
|
|
69806
|
+
var RcTeleportInputSchema = external_exports.strictObject({
|
|
69807
|
+
session: external_exports.string().min(1),
|
|
69808
|
+
marker: external_exports.string().min(1)
|
|
69809
|
+
});
|
|
69810
|
+
var RcListOutputSchema = external_exports.strictObject({ sessions: external_exports.readonly(external_exports.array(RcSessionSummarySchema)) });
|
|
69811
|
+
var RcStatusOutputSchema = external_exports.strictObject({ statuses: external_exports.readonly(external_exports.array(RcSessionStatusSchema)) });
|
|
69812
|
+
var RcPendingOutputSchema = external_exports.strictObject({ pending: external_exports.readonly(external_exports.array(RcPendingRequestSummarySchema)) });
|
|
69813
|
+
var RcWriteOutputSchema = external_exports.strictObject({
|
|
69814
|
+
session: external_exports.string(),
|
|
69815
|
+
sequenceNums: external_exports.readonly(external_exports.array(external_exports.number()))
|
|
69816
|
+
});
|
|
69817
|
+
var RcControlWriteOutputSchema = external_exports.strictObject({
|
|
69818
|
+
session: external_exports.string(),
|
|
69819
|
+
request: external_exports.string(),
|
|
69820
|
+
sequenceNums: external_exports.readonly(external_exports.array(external_exports.number()))
|
|
69821
|
+
});
|
|
69822
|
+
var RcAnswerOutputSchema = external_exports.strictObject({
|
|
69823
|
+
session: external_exports.string(),
|
|
69824
|
+
request: external_exports.string(),
|
|
69825
|
+
sequenceNums: external_exports.readonly(external_exports.array(external_exports.number()))
|
|
69826
|
+
});
|
|
69827
|
+
|
|
69828
|
+
// src/frontdoor/controlSchemas.ts
|
|
69643
69829
|
var UsageListOutputSchema = external_exports.strictObject({ snapshots: external_exports.readonly(external_exports.array(UsageSnapshotSchema)) });
|
|
69644
69830
|
var UsageWindowsInputSchema = external_exports.strictObject({
|
|
69645
69831
|
identity: external_exports.string().min(1),
|
|
@@ -69663,6 +69849,12 @@ var UsageWindowsOutputSchema = external_exports.strictObject({
|
|
|
69663
69849
|
fiveHour: EffectiveWindowSchema.optional(),
|
|
69664
69850
|
sevenDay: EffectiveWindowSchema.optional()
|
|
69665
69851
|
});
|
|
69852
|
+
var UsageLiveOutputSchema = external_exports.strictObject({
|
|
69853
|
+
/** The freshest observation the door holds, never narrowed by the read's session filter because it is the door's single latest statement of the account's quota; absent while no rate_limit_event has been filed at all. */
|
|
69854
|
+
latest: RcLiveRateLimitSchema.optional(),
|
|
69855
|
+
/** One observation per session whose stream has filed a rate_limit_event this door generation. */
|
|
69856
|
+
sessions: external_exports.readonly(external_exports.array(RcLiveRateLimitSchema))
|
|
69857
|
+
});
|
|
69666
69858
|
var FrontDoorSessionStatusSchema = external_exports.strictObject({
|
|
69667
69859
|
pid: external_exports.int().positive(),
|
|
69668
69860
|
startedAt: external_exports.number(),
|
|
@@ -71966,133 +72158,6 @@ var RPCHandler = class extends NodeHttpHandler {
|
|
|
71966
72158
|
|
|
71967
72159
|
// src/frontdoor/rcApi.ts
|
|
71968
72160
|
var import_undici2 = __toESM(require_undici(), 1);
|
|
71969
|
-
|
|
71970
|
-
// src/frontdoor/rcSchemas.ts
|
|
71971
|
-
var RcPermissionModeSchema = external_exports.enum(RC_PERMISSION_MODES);
|
|
71972
|
-
var RcSessionSummarySchema = external_exports.strictObject({
|
|
71973
|
-
id: external_exports.string(),
|
|
71974
|
-
createdAt: external_exports.number(),
|
|
71975
|
-
lastSeenAt: external_exports.number()
|
|
71976
|
-
});
|
|
71977
|
-
function workerFactSchema(value2) {
|
|
71978
|
-
return external_exports.strictObject({ value: value2, observedAt: external_exports.number() });
|
|
71979
|
-
}
|
|
71980
|
-
var RcPendingRequestSummarySchema = external_exports.strictObject({
|
|
71981
|
-
sessionId: external_exports.string(),
|
|
71982
|
-
requestId: external_exports.string(),
|
|
71983
|
-
type: external_exports.string(),
|
|
71984
|
-
summary: external_exports.string(),
|
|
71985
|
-
observedAt: external_exports.number()
|
|
71986
|
-
});
|
|
71987
|
-
var RcSessionStatusSchema = external_exports.strictObject({
|
|
71988
|
-
...RcSessionSummarySchema.shape,
|
|
71989
|
-
workerState: workerFactSchema(external_exports.string()).optional(),
|
|
71990
|
-
workerIdleSeconds: workerFactSchema(external_exports.number()).optional(),
|
|
71991
|
-
pending: external_exports.readonly(external_exports.array(RcPendingRequestSummarySchema))
|
|
71992
|
-
});
|
|
71993
|
-
var RcStreamEnvelopeSchema = external_exports.looseObject({
|
|
71994
|
-
/** The envelope's own event id, when the host sent one. */
|
|
71995
|
-
event_id: external_exports.string().optional(),
|
|
71996
|
-
/** The envelope's event type, the discriminator a consumer switches on (`control_request`, `user`, and kin). */
|
|
71997
|
-
event_type: external_exports.string(),
|
|
71998
|
-
/** The sequence number the host assigned, the value a resume continues after. */
|
|
71999
|
-
sequence_num: external_exports.int(),
|
|
72000
|
-
/** Who emitted the event (`worker` for the CLI's half, a client id for a client's). */
|
|
72001
|
-
source: external_exports.string(),
|
|
72002
|
-
/** The event's payload, carried verbatim: its shape is the payload family's, narrowed by whichever consumer needs it. Optional in the schema's own type because the door forwards the host's envelope as it arrived, asserting only the fields it relies on itself. */
|
|
72003
|
-
payload: external_exports.unknown().optional(),
|
|
72004
|
-
/** When the host created the event; the protocol's own type for this field is not established here, so it is forwarded rather than asserted. */
|
|
72005
|
-
created_at: external_exports.unknown().optional()
|
|
72006
|
-
});
|
|
72007
|
-
var RcStreamEventSchema = external_exports.strictObject({
|
|
72008
|
-
session: external_exports.string(),
|
|
72009
|
-
envelope: RcStreamEnvelopeSchema
|
|
72010
|
-
});
|
|
72011
|
-
var RcSessionQuerySchema = external_exports.strictObject({
|
|
72012
|
-
session: external_exports.string().min(1).optional()
|
|
72013
|
-
});
|
|
72014
|
-
var RcSendInputSchema = external_exports.strictObject({
|
|
72015
|
-
session: external_exports.string().min(1),
|
|
72016
|
-
text: external_exports.string().min(1)
|
|
72017
|
-
});
|
|
72018
|
-
var RcAnswerInputSchema = external_exports.strictObject({
|
|
72019
|
-
session: external_exports.string().min(1),
|
|
72020
|
-
request: external_exports.string().min(1),
|
|
72021
|
-
approve: external_exports.boolean(),
|
|
72022
|
-
text: external_exports.string().optional()
|
|
72023
|
-
}).refine((input2) => !input2.approve || input2.text === void 0 || input2.text === "", { message: "an approval carries no text (the protocol's allow result has no message field); text is the denial message" });
|
|
72024
|
-
var RcInterruptInputSchema = external_exports.strictObject({
|
|
72025
|
-
session: external_exports.string().min(1)
|
|
72026
|
-
});
|
|
72027
|
-
var RcSetModelInputSchema = external_exports.strictObject({
|
|
72028
|
-
session: external_exports.string().min(1),
|
|
72029
|
-
model: external_exports.string().min(1)
|
|
72030
|
-
});
|
|
72031
|
-
var RcSetPermissionModeInputSchema = external_exports.strictObject({
|
|
72032
|
-
session: external_exports.string().min(1),
|
|
72033
|
-
mode: RcPermissionModeSchema
|
|
72034
|
-
});
|
|
72035
|
-
var RcEndSessionInputSchema = external_exports.strictObject({
|
|
72036
|
-
session: external_exports.string().min(1),
|
|
72037
|
-
reason: external_exports.string().min(1).optional()
|
|
72038
|
-
});
|
|
72039
|
-
var RcGetUsageInputSchema = external_exports.strictObject({
|
|
72040
|
-
session: external_exports.string().min(1),
|
|
72041
|
-
skipBehaviors: external_exports.boolean().optional()
|
|
72042
|
-
});
|
|
72043
|
-
var RcGetContextUsageInputSchema = external_exports.strictObject({
|
|
72044
|
-
session: external_exports.string().min(1),
|
|
72045
|
-
detail: external_exports.enum(RC_CONTEXT_USAGE_DETAILS).optional()
|
|
72046
|
-
});
|
|
72047
|
-
var RcReadFileInputSchema = external_exports.strictObject({
|
|
72048
|
-
session: external_exports.string().min(1),
|
|
72049
|
-
path: external_exports.string().min(1),
|
|
72050
|
-
maxBytes: external_exports.number().int().positive().optional(),
|
|
72051
|
-
encoding: external_exports.enum(RC_READ_FILE_ENCODINGS).optional()
|
|
72052
|
-
});
|
|
72053
|
-
var RcFileSuggestionsInputSchema = external_exports.strictObject({
|
|
72054
|
-
session: external_exports.string().min(1),
|
|
72055
|
-
query: external_exports.string()
|
|
72056
|
-
});
|
|
72057
|
-
var RcKeepAliveInputSchema = external_exports.strictObject({
|
|
72058
|
-
session: external_exports.string().min(1)
|
|
72059
|
-
});
|
|
72060
|
-
var RcMcpStatusInputSchema = external_exports.strictObject({
|
|
72061
|
-
session: external_exports.string().min(1)
|
|
72062
|
-
});
|
|
72063
|
-
var RcMcpReconnectInputSchema = external_exports.strictObject({
|
|
72064
|
-
session: external_exports.string().min(1),
|
|
72065
|
-
serverName: external_exports.string().min(1)
|
|
72066
|
-
});
|
|
72067
|
-
var RcMcpAuthenticateInputSchema = external_exports.strictObject({
|
|
72068
|
-
session: external_exports.string().min(1),
|
|
72069
|
-
serverName: external_exports.string().min(1),
|
|
72070
|
-
redirectUri: external_exports.string().min(1)
|
|
72071
|
-
});
|
|
72072
|
-
var RcMcpOAuthCallbackUrlInputSchema = external_exports.strictObject({
|
|
72073
|
-
session: external_exports.string().min(1),
|
|
72074
|
-
serverName: external_exports.string().min(1),
|
|
72075
|
-
callbackUrl: external_exports.string().min(1)
|
|
72076
|
-
});
|
|
72077
|
-
var RcListOutputSchema = external_exports.strictObject({ sessions: external_exports.readonly(external_exports.array(RcSessionSummarySchema)) });
|
|
72078
|
-
var RcStatusOutputSchema = external_exports.strictObject({ statuses: external_exports.readonly(external_exports.array(RcSessionStatusSchema)) });
|
|
72079
|
-
var RcPendingOutputSchema = external_exports.strictObject({ pending: external_exports.readonly(external_exports.array(RcPendingRequestSummarySchema)) });
|
|
72080
|
-
var RcWriteOutputSchema = external_exports.strictObject({
|
|
72081
|
-
session: external_exports.string(),
|
|
72082
|
-
sequenceNums: external_exports.readonly(external_exports.array(external_exports.number()))
|
|
72083
|
-
});
|
|
72084
|
-
var RcControlWriteOutputSchema = external_exports.strictObject({
|
|
72085
|
-
session: external_exports.string(),
|
|
72086
|
-
request: external_exports.string(),
|
|
72087
|
-
sequenceNums: external_exports.readonly(external_exports.array(external_exports.number()))
|
|
72088
|
-
});
|
|
72089
|
-
var RcAnswerOutputSchema = external_exports.strictObject({
|
|
72090
|
-
session: external_exports.string(),
|
|
72091
|
-
request: external_exports.string(),
|
|
72092
|
-
sequenceNums: external_exports.readonly(external_exports.array(external_exports.number()))
|
|
72093
|
-
});
|
|
72094
|
-
|
|
72095
|
-
// src/frontdoor/rcApi.ts
|
|
72096
72161
|
var RC_ORPC_PATH_PREFIX = "/__agent-shim/orpc";
|
|
72097
72162
|
var RC_SUBSCRIBER_BUFFER_EVENTS = 100;
|
|
72098
72163
|
function doorApiAuth(expectedToken) {
|
|
@@ -72158,6 +72223,7 @@ function createRcApiRouter(deps) {
|
|
|
72158
72223
|
mcpReconnect: authed.input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input: input2 }) => ({ session: input2.session, ...deliveredControl(input2.session, await deps.mcpReconnect(input2.session, input2.serverName)) })),
|
|
72159
72224
|
mcpAuthenticate: authed.input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input: input2 }) => ({ session: input2.session, ...deliveredControl(input2.session, await deps.mcpAuthenticate(input2.session, input2.serverName, input2.redirectUri)) })),
|
|
72160
72225
|
mcpOAuthCallbackUrl: authed.input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input: input2 }) => ({ session: input2.session, ...deliveredControl(input2.session, await deps.mcpOAuthCallbackUrl(input2.session, input2.serverName, input2.callbackUrl)) })),
|
|
72226
|
+
teleport: authed.input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input: input2 }) => ({ session: input2.session, sequenceNums: delivered(input2.session, await deps.teleport(input2.session, input2.marker)) })),
|
|
72161
72227
|
subscribe: authed.input(RcSessionQuerySchema).output(eventIterator(RcStreamEventSchema)).handler(async function* ({ input: input2, signal }) {
|
|
72162
72228
|
const queue = [];
|
|
72163
72229
|
let wake;
|
|
@@ -72303,6 +72369,16 @@ function createControlApiRouter(deps) {
|
|
|
72303
72369
|
...unified?.fiveHour === void 0 ? {} : { fiveHour: effectiveWindow(unified.fiveHour, now) },
|
|
72304
72370
|
...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
|
|
72305
72371
|
};
|
|
72372
|
+
}),
|
|
72373
|
+
live: authed.input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input: input2 }) => {
|
|
72374
|
+
const sessions = deps.liveRateLimits(input2.session);
|
|
72375
|
+
if (input2.session !== void 0 && sessions.length === 0) {
|
|
72376
|
+
if (deps.list().some((session) => session.id === input2.session)) {
|
|
72377
|
+
throw new ORPCError("NOT_FOUND", { message: `session ${input2.session} has filed no rate_limit_event on its stream yet: the worker emits one only once a turn has completed, so retry after this session's next turn` });
|
|
72378
|
+
}
|
|
72379
|
+
throw new ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input2.session) });
|
|
72380
|
+
}
|
|
72381
|
+
return { latest: deps.latestRateLimit(), sessions };
|
|
72306
72382
|
})
|
|
72307
72383
|
},
|
|
72308
72384
|
frontdoor: {
|
|
@@ -73735,9 +73811,232 @@ function attachingProviderCredential(route, deps) {
|
|
|
73735
73811
|
// src/frontdoor/rcCommands.ts
|
|
73736
73812
|
var import_node_crypto14 = require("node:crypto");
|
|
73737
73813
|
|
|
73814
|
+
// src/frontdoor/rcLiveUsage.ts
|
|
73815
|
+
var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
|
|
73816
|
+
function isRecord4(value2) {
|
|
73817
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
73818
|
+
}
|
|
73819
|
+
function rcRateLimitInfoOf(event) {
|
|
73820
|
+
const payload = event.envelope.payload;
|
|
73821
|
+
if (!isRecord4(payload) || payload.type !== RC_RATE_LIMIT_EVENT_TYPE) {
|
|
73822
|
+
return void 0;
|
|
73823
|
+
}
|
|
73824
|
+
if (!isRecord4(payload.rate_limit_info)) {
|
|
73825
|
+
return void 0;
|
|
73826
|
+
}
|
|
73827
|
+
const parsed = RcRateLimitInfoSchema.safeParse(payload.rate_limit_info);
|
|
73828
|
+
return parsed.success ? parsed.data : void 0;
|
|
73829
|
+
}
|
|
73830
|
+
function createRcLiveUsage(deps) {
|
|
73831
|
+
const observed = /* @__PURE__ */ new Map();
|
|
73832
|
+
deps.hub.subscribe([DOOR_EVENT_SOURCE_RC], (event) => {
|
|
73833
|
+
const stream = RcStreamEventSchema.safeParse(event.payload);
|
|
73834
|
+
if (!stream.success) {
|
|
73835
|
+
return;
|
|
73836
|
+
}
|
|
73837
|
+
const rateLimit = rcRateLimitInfoOf(stream.data);
|
|
73838
|
+
if (rateLimit === void 0) {
|
|
73839
|
+
return;
|
|
73840
|
+
}
|
|
73841
|
+
observed.set(stream.data.session, { session: stream.data.session, observedAt: deps.now(), rateLimit });
|
|
73842
|
+
});
|
|
73843
|
+
const sorted = () => [...observed.values()].sort((left, right) => left.observedAt - right.observedAt || (left.session < right.session ? -1 : 1));
|
|
73844
|
+
return {
|
|
73845
|
+
liveOf: (sessionId) => sorted().filter((entry) => sessionId === void 0 || entry.session === sessionId),
|
|
73846
|
+
latestOf: () => sorted().at(-1)
|
|
73847
|
+
};
|
|
73848
|
+
}
|
|
73849
|
+
|
|
73738
73850
|
// src/frontdoor/rcSelfHostMint.ts
|
|
73739
73851
|
var import_node_path34 = __toESM(require("node:path"), 1);
|
|
73740
73852
|
|
|
73853
|
+
// src/frontdoor/rcSelfHostEndpoints.ts
|
|
73854
|
+
var RC_SOURCE_WORKER = "worker";
|
|
73855
|
+
var RC_SOURCE_CLIENT = "client";
|
|
73856
|
+
function isRecord5(value2) {
|
|
73857
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
73858
|
+
}
|
|
73859
|
+
function parseJsonObject2(body) {
|
|
73860
|
+
let parsed;
|
|
73861
|
+
try {
|
|
73862
|
+
parsed = JSON.parse(body);
|
|
73863
|
+
} catch {
|
|
73864
|
+
return void 0;
|
|
73865
|
+
}
|
|
73866
|
+
return isRecord5(parsed) ? parsed : void 0;
|
|
73867
|
+
}
|
|
73868
|
+
function nonEmptyString2(record2, field) {
|
|
73869
|
+
const value2 = record2 === void 0 ? void 0 : record2[field];
|
|
73870
|
+
return typeof value2 === "string" && value2 !== "" ? value2 : void 0;
|
|
73871
|
+
}
|
|
73872
|
+
function numberOf(record2, field) {
|
|
73873
|
+
const value2 = record2 === void 0 ? void 0 : record2[field];
|
|
73874
|
+
if (typeof value2 === "number" && Number.isFinite(value2)) {
|
|
73875
|
+
return value2;
|
|
73876
|
+
}
|
|
73877
|
+
if (typeof value2 === "string" && /^[0-9]+$/.test(value2)) {
|
|
73878
|
+
return Number(value2);
|
|
73879
|
+
}
|
|
73880
|
+
return void 0;
|
|
73881
|
+
}
|
|
73882
|
+
function pageOfRcChannel(url2, rows, idOf, rowOf) {
|
|
73883
|
+
const query = new URL(url2, "http://127.0.0.1").searchParams;
|
|
73884
|
+
const anchor2 = query.get("after_event_id") ?? query.get("cursor");
|
|
73885
|
+
const rawLimit = query.get("limit");
|
|
73886
|
+
const limit = rawLimit === null ? void 0 : numberOf({ value: rawLimit }, "value");
|
|
73887
|
+
if (limit !== void 0 && limit < 1) {
|
|
73888
|
+
return { error: "the limit names a whole number of rows of at least one" };
|
|
73889
|
+
}
|
|
73890
|
+
const from = anchor2 === null ? 0 : rows.findIndex((row) => idOf(row) === anchor2) + 1;
|
|
73891
|
+
if (anchor2 !== null && from === 0) {
|
|
73892
|
+
return { error: `the anchor names an event id this surface holds no row for: ${anchor2}` };
|
|
73893
|
+
}
|
|
73894
|
+
const page = limit === void 0 ? rows.slice(from) : rows.slice(from, from + limit);
|
|
73895
|
+
const last = page[page.length - 1];
|
|
73896
|
+
return { data: page.map(rowOf), ...last === void 0 ? {} : { next_cursor: idOf(last) } };
|
|
73897
|
+
}
|
|
73898
|
+
async function serveRcClientChannels(ctx, tail, method, maxBatchEvents) {
|
|
73899
|
+
const { request: request7, response, session } = ctx;
|
|
73900
|
+
if (tail === "client/presence" && method === "POST") {
|
|
73901
|
+
const body = parseJsonObject2(await ctx.readBody(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
73902
|
+
const clientId = nonEmptyString2(body, "client_id");
|
|
73903
|
+
const clear = body?.clear;
|
|
73904
|
+
if (clientId === void 0 || clear !== void 0 && typeof clear !== "boolean") {
|
|
73905
|
+
await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "a presence announcement is JSON naming a non-empty client_id, with clear only as a boolean or absent" } });
|
|
73906
|
+
return true;
|
|
73907
|
+
}
|
|
73908
|
+
if (clear === true) {
|
|
73909
|
+
session.clients.delete(clientId);
|
|
73910
|
+
ctx.log?.(`rc selfhost ${session.id}: client ${clientId} cleared its presence`);
|
|
73911
|
+
} else {
|
|
73912
|
+
session.clients.set(clientId, ctx.now());
|
|
73913
|
+
ctx.log?.(`rc selfhost ${session.id}: client ${clientId} announced its presence${session.clients.size === 1 ? "" : ` (${String(session.clients.size)} clients now announced)`}`);
|
|
73914
|
+
}
|
|
73915
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, { refresh_after_seconds: ctx.presenceRefreshSeconds });
|
|
73916
|
+
return true;
|
|
73917
|
+
}
|
|
73918
|
+
if (tail === "mark_read" && method === "POST") {
|
|
73919
|
+
const body = parseJsonObject2(await ctx.readBody(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
73920
|
+
const eventId = nonEmptyString2(body, "event_id");
|
|
73921
|
+
const clientId = nonEmptyString2(body, "client_id");
|
|
73922
|
+
if (body !== void 0 && "event_id" in body && eventId === void 0 || "client_id" in (body ?? {}) && clientId === void 0) {
|
|
73923
|
+
await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "a read receipt is JSON naming the event_id it read or none for the whole session, and client_id only as a non-empty string or absent" } });
|
|
73924
|
+
return true;
|
|
73925
|
+
}
|
|
73926
|
+
const receipt = ctx.publish(session, clientId ?? RC_SOURCE_CLIENT, { type: "mark_read", ...eventId === void 0 ? {} : { event_id: eventId }, ...clientId === void 0 ? {} : { client_id: clientId } }, true);
|
|
73927
|
+
ctx.log?.(`rc selfhost ${session.id}: ${clientId === void 0 ? "an unnamed client" : `client ${clientId}`} marked ${eventId === void 0 ? "the session read" : `event ${eventId} read`} as sequence ${String(receipt.sequenceNum)}`);
|
|
73928
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, {});
|
|
73929
|
+
return true;
|
|
73930
|
+
}
|
|
73931
|
+
if (tail === "teleport-events" && method === "POST") {
|
|
73932
|
+
const body = parseJsonObject2(await ctx.readBody(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
73933
|
+
const events = body?.events;
|
|
73934
|
+
if (!Array.isArray(events) || events.length === 0 || events.length > maxBatchEvents) {
|
|
73935
|
+
await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: `a teleport write is a non-empty array of at most ${String(maxBatchEvents)} events` } });
|
|
73936
|
+
return true;
|
|
73937
|
+
}
|
|
73938
|
+
const results = [];
|
|
73939
|
+
for (const event of events) {
|
|
73940
|
+
if (!isRecord5(event) || !isRecord5(event.payload)) {
|
|
73941
|
+
await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a teleport write is an object carrying one payload object" } });
|
|
73942
|
+
return true;
|
|
73943
|
+
}
|
|
73944
|
+
const published = ctx.publish(session, RC_SOURCE_CLIENT, event.payload);
|
|
73945
|
+
results.push({ sequence_num: String(published.sequenceNum), duplicate: published.duplicate });
|
|
73946
|
+
}
|
|
73947
|
+
ctx.sweep();
|
|
73948
|
+
ctx.log?.(`rc selfhost ${session.id}: teleport write published ${String(results.length)} marker event(s)`);
|
|
73949
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, { results });
|
|
73950
|
+
return true;
|
|
73951
|
+
}
|
|
73952
|
+
if (tail === "teleport-events" && method === "GET") {
|
|
73953
|
+
const page = pageOfRcChannel(request7.url, session.events, (event) => event.eventId, (event) => ({ event_id: event.eventId, payload: event.payload }));
|
|
73954
|
+
if ("error" in page) {
|
|
73955
|
+
await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: page.error } });
|
|
73956
|
+
return true;
|
|
73957
|
+
}
|
|
73958
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, page);
|
|
73959
|
+
return true;
|
|
73960
|
+
}
|
|
73961
|
+
return false;
|
|
73962
|
+
}
|
|
73963
|
+
var compatSessionRow = (session, now) => ({ id: session.id, title: session.title, created_at: new Date(session.createdAt).toISOString(), updated_at: new Date(now()).toISOString(), session_status: "active" });
|
|
73964
|
+
async function serveRcCompatSessions(ctx, pathname, compatPath) {
|
|
73965
|
+
const { request: request7, response } = ctx;
|
|
73966
|
+
const method = request7.method.toUpperCase();
|
|
73967
|
+
if (pathname === compatPath) {
|
|
73968
|
+
if (method !== "GET") {
|
|
73969
|
+
await ctx.answerJson(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the compatibility session list is a GET" } });
|
|
73970
|
+
return;
|
|
73971
|
+
}
|
|
73972
|
+
const listRefusal = ctx.credentialRefusal(request7.headers);
|
|
73973
|
+
if (listRefusal !== void 0) {
|
|
73974
|
+
await ctx.unauthorized(response, listRefusal);
|
|
73975
|
+
return;
|
|
73976
|
+
}
|
|
73977
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, { data: [...ctx.sessions.values()].map((session2) => compatSessionRow(session2, ctx.now)) });
|
|
73978
|
+
return;
|
|
73979
|
+
}
|
|
73980
|
+
const rest = pathname.slice(`${compatPath}/`.length);
|
|
73981
|
+
const slash = rest.indexOf("/");
|
|
73982
|
+
const address = slash === -1 ? rest : rest.slice(0, slash);
|
|
73983
|
+
const compatTail = slash === -1 ? "" : rest.slice(slash + 1);
|
|
73984
|
+
const refusal = ctx.credentialRefusal(request7.headers);
|
|
73985
|
+
if (refusal !== void 0) {
|
|
73986
|
+
await ctx.unauthorized(response, refusal);
|
|
73987
|
+
return;
|
|
73988
|
+
}
|
|
73989
|
+
const session = ctx.sessions.get(address) ?? ctx.sessions.get(`cse_${address}`);
|
|
73990
|
+
if (compatTail === "") {
|
|
73991
|
+
if (method === "GET") {
|
|
73992
|
+
if (session === void 0) {
|
|
73993
|
+
await ctx.answerJson(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `Session not found: ${address}` } });
|
|
73994
|
+
return;
|
|
73995
|
+
}
|
|
73996
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, compatSessionRow(session, ctx.now));
|
|
73997
|
+
return;
|
|
73998
|
+
}
|
|
73999
|
+
if (method === "PATCH" || method === "PUT") {
|
|
74000
|
+
if (session === void 0) {
|
|
74001
|
+
await ctx.answerJson(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `Session not found: ${address}` } });
|
|
74002
|
+
return;
|
|
74003
|
+
}
|
|
74004
|
+
const body = parseJsonObject2(await ctx.readBody(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74005
|
+
const title = nonEmptyString2(body, "title");
|
|
74006
|
+
if (title === void 0) {
|
|
74007
|
+
await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "a compatibility session update is JSON naming a non-empty title" } });
|
|
74008
|
+
return;
|
|
74009
|
+
}
|
|
74010
|
+
session.title = title;
|
|
74011
|
+
session.lastTrafficAt = ctx.now();
|
|
74012
|
+
ctx.log?.(`rc selfhost ${session.id}: retitled through the compatibility family`);
|
|
74013
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, compatSessionRow(session, ctx.now));
|
|
74014
|
+
return;
|
|
74015
|
+
}
|
|
74016
|
+
await ctx.answerJson(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the compatibility session read is a GET and its update a PATCH or PUT" } });
|
|
74017
|
+
return;
|
|
74018
|
+
}
|
|
74019
|
+
if ((compatTail === "archive" || compatTail === "unarchive") && method === "POST") {
|
|
74020
|
+
await ctx.readBody(request7.body, CONTROL_BODY_CAP_BYTES);
|
|
74021
|
+
if (session === void 0) {
|
|
74022
|
+
await ctx.answerJson(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `Session not found: ${address}` } });
|
|
74023
|
+
return;
|
|
74024
|
+
}
|
|
74025
|
+
if (compatTail === "unarchive") {
|
|
74026
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, compatSessionRow(session, ctx.now));
|
|
74027
|
+
return;
|
|
74028
|
+
}
|
|
74029
|
+
for (const sink of [...session.workerStreams, ...session.clientStreams]) {
|
|
74030
|
+
sink.retire();
|
|
74031
|
+
}
|
|
74032
|
+
ctx.sessions.delete(session.id);
|
|
74033
|
+
ctx.log?.(`rc selfhost ${session.id}: archived through the compatibility family`);
|
|
74034
|
+
await ctx.answerJson(response, HTTP_STATUS.ok, {});
|
|
74035
|
+
return;
|
|
74036
|
+
}
|
|
74037
|
+
await ctx.answerJson(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `the compatibility session family serves no path "${compatTail}"` } });
|
|
74038
|
+
}
|
|
74039
|
+
|
|
73741
74040
|
// src/frontdoor/rcWebFetch.ts
|
|
73742
74041
|
var dns2 = __toESM(require("node:dns"), 1);
|
|
73743
74042
|
var http6 = __toESM(require("node:http"), 1);
|
|
@@ -74006,21 +74305,19 @@ var RC_PRESENCE_REFRESH_SECONDS = 60;
|
|
|
74006
74305
|
var RC_SELF_HOST_MAX_BATCH_EVENTS = 100;
|
|
74007
74306
|
var RC_SELF_HOST_WORKER_EPOCH = 1;
|
|
74008
74307
|
var RC_STREAM_EVENT_NAME = "client_event";
|
|
74009
|
-
var RC_SOURCE_WORKER = "worker";
|
|
74010
|
-
var RC_SOURCE_CLIENT = "client";
|
|
74011
74308
|
var CONFLICT_REASON_HEADER2 = "x-ccr-conflict-reason";
|
|
74012
74309
|
var CONFLICT_REASON_EPOCH_STALE = "epoch_stale";
|
|
74013
|
-
function
|
|
74310
|
+
function isRecord6(value2) {
|
|
74014
74311
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
74015
74312
|
}
|
|
74016
74313
|
function isWebSearchRefusal(value2) {
|
|
74017
74314
|
return !Array.isArray(value2);
|
|
74018
74315
|
}
|
|
74019
|
-
function
|
|
74316
|
+
function nonEmptyString3(record2, field) {
|
|
74020
74317
|
const value2 = record2 === void 0 ? void 0 : record2[field];
|
|
74021
74318
|
return typeof value2 === "string" && value2 !== "" ? value2 : void 0;
|
|
74022
74319
|
}
|
|
74023
|
-
function
|
|
74320
|
+
function numberOf2(record2, field) {
|
|
74024
74321
|
const value2 = record2 === void 0 ? void 0 : record2[field];
|
|
74025
74322
|
if (typeof value2 === "number" && Number.isFinite(value2)) {
|
|
74026
74323
|
return value2;
|
|
@@ -74087,14 +74384,14 @@ async function readBody3(request7, capBytes) {
|
|
|
74087
74384
|
});
|
|
74088
74385
|
});
|
|
74089
74386
|
}
|
|
74090
|
-
function
|
|
74387
|
+
function parseJsonObject3(body) {
|
|
74091
74388
|
let parsed;
|
|
74092
74389
|
try {
|
|
74093
74390
|
parsed = JSON.parse(body);
|
|
74094
74391
|
} catch {
|
|
74095
74392
|
return void 0;
|
|
74096
74393
|
}
|
|
74097
|
-
return
|
|
74394
|
+
return isRecord6(parsed) ? parsed : void 0;
|
|
74098
74395
|
}
|
|
74099
74396
|
function mintWorkerJwt(randomToken, issuedAt) {
|
|
74100
74397
|
const encode3 = (value2) => Buffer.from(JSON.stringify(value2), "utf8").toString("base64url");
|
|
@@ -74117,11 +74414,16 @@ function createRcSelfHostSurface(deps) {
|
|
|
74117
74414
|
for (const session of sessions.values()) {
|
|
74118
74415
|
while (session.events[0] !== void 0 && now - session.events[0].storedAt > RC_SELF_HOST_RETENTION_MS) {
|
|
74119
74416
|
const dropped = session.events.shift();
|
|
74120
|
-
const uuid3 = dropped === void 0 ? void 0 :
|
|
74417
|
+
const uuid3 = dropped === void 0 ? void 0 : nonEmptyString3(dropped.payload, "uuid");
|
|
74121
74418
|
if (uuid3 !== void 0) {
|
|
74122
74419
|
session.seenPayloadUuids.delete(uuid3);
|
|
74123
74420
|
}
|
|
74124
74421
|
}
|
|
74422
|
+
for (const [clientId, lastSeenAt] of session.clients) {
|
|
74423
|
+
if (now - lastSeenAt > RC_SELF_HOST_RETENTION_MS) {
|
|
74424
|
+
session.clients.delete(clientId);
|
|
74425
|
+
}
|
|
74426
|
+
}
|
|
74125
74427
|
if (session.workerStreams.size === 0 && session.clientStreams.size === 0 && now - session.lastTrafficAt > RC_SELF_HOST_RETENTION_MS) {
|
|
74126
74428
|
sessions.delete(session.id);
|
|
74127
74429
|
}
|
|
@@ -74160,7 +74462,7 @@ function createRcSelfHostSurface(deps) {
|
|
|
74160
74462
|
const frameOf = (event) => {
|
|
74161
74463
|
const envelope = {
|
|
74162
74464
|
event_id: event.eventId,
|
|
74163
|
-
event_type:
|
|
74465
|
+
event_type: nonEmptyString3(event.payload, "type") ?? "event",
|
|
74164
74466
|
sequence_num: event.sequenceNum,
|
|
74165
74467
|
source: event.source,
|
|
74166
74468
|
payload: event.payload,
|
|
@@ -74174,7 +74476,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
74174
74476
|
};
|
|
74175
74477
|
const holdStream = async (session, which, wantsReplay, request7, response) => {
|
|
74176
74478
|
const url2 = new URL(request7.url, "http://127.0.0.1");
|
|
74177
|
-
const cursor3 =
|
|
74479
|
+
const cursor3 = numberOf2({ value: url2.searchParams.get("from_sequence_num") }, "value") ?? numberOf2({ value: singleHeader2(request7.headers, "last-event-id") }, "value");
|
|
74178
74480
|
const replay = cursor3 === void 0 ? [] : session.events.filter((event) => wantsReplay(event) && event.sequenceNum > cursor3);
|
|
74179
74481
|
response.start(HTTP_STATUS.ok, { "content-type": "text/event-stream", "cache-control": "no-cache" });
|
|
74180
74482
|
response.flush();
|
|
@@ -74203,8 +74505,8 @@ data: ${JSON.stringify(envelope)}
|
|
|
74203
74505
|
sink.retire();
|
|
74204
74506
|
response.end();
|
|
74205
74507
|
};
|
|
74206
|
-
const publish = (session, source, payload) => {
|
|
74207
|
-
const uuid3 =
|
|
74508
|
+
const publish = (session, source, payload, toWorker = source === RC_SOURCE_CLIENT) => {
|
|
74509
|
+
const uuid3 = nonEmptyString3(payload, "uuid");
|
|
74208
74510
|
const duplicate = uuid3 !== void 0 && session.seenPayloadUuids.has(uuid3);
|
|
74209
74511
|
session.sequenceNum += 1;
|
|
74210
74512
|
const event = {
|
|
@@ -74212,9 +74514,9 @@ data: ${JSON.stringify(envelope)}
|
|
|
74212
74514
|
eventId: uuid3 ?? deps.newUuid(),
|
|
74213
74515
|
source,
|
|
74214
74516
|
// The one enrichment the real service was observed making on the live rig's stream: the wall-clock instant it took the write. The worker's handler ignores it; the door's own parser forwards it verbatim.
|
|
74215
|
-
payload: source ===
|
|
74517
|
+
payload: source === RC_SOURCE_WORKER ? payload : { ...payload, server_received_wall_ms: deps.now() },
|
|
74216
74518
|
createdAt: new Date(deps.now()).toISOString(),
|
|
74217
|
-
toWorker
|
|
74519
|
+
toWorker,
|
|
74218
74520
|
storedAt: deps.now()
|
|
74219
74521
|
};
|
|
74220
74522
|
session.events.push(event);
|
|
@@ -74262,8 +74564,26 @@ data: ${JSON.stringify(envelope)}
|
|
|
74262
74564
|
}
|
|
74263
74565
|
session.lastTrafficAt = deps.now();
|
|
74264
74566
|
if (tail === "") {
|
|
74567
|
+
if (method === "PATCH" || method === "PUT") {
|
|
74568
|
+
const refusal = credentialRefusal(request7.headers);
|
|
74569
|
+
if (refusal !== void 0) {
|
|
74570
|
+
await unauthorized(response, refusal);
|
|
74571
|
+
return;
|
|
74572
|
+
}
|
|
74573
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74574
|
+
const title = nonEmptyString3(body, "title");
|
|
74575
|
+
if (title === void 0) {
|
|
74576
|
+
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "a session update is JSON naming a non-empty title" } });
|
|
74577
|
+
return;
|
|
74578
|
+
}
|
|
74579
|
+
session.title = title;
|
|
74580
|
+
session.lastTrafficAt = deps.now();
|
|
74581
|
+
deps.log?.(`rc selfhost ${session.id}: retitled at its client's request`);
|
|
74582
|
+
await answerJson2(response, HTTP_STATUS.ok, {});
|
|
74583
|
+
return;
|
|
74584
|
+
}
|
|
74265
74585
|
if (method !== "GET") {
|
|
74266
|
-
await answerJson2(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the session read is a GET" } });
|
|
74586
|
+
await answerJson2(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the session read is a GET, and its update a PATCH or PUT" } });
|
|
74267
74587
|
return;
|
|
74268
74588
|
}
|
|
74269
74589
|
await answerJson2(response, HTTP_STATUS.ok, { session: { id: session.id, title: session.title, created_at: new Date(session.createdAt).toISOString(), status: "active" } });
|
|
@@ -74308,17 +74628,17 @@ data: ${JSON.stringify(envelope)}
|
|
|
74308
74628
|
return;
|
|
74309
74629
|
}
|
|
74310
74630
|
if (workerTail === "" && method === "PUT") {
|
|
74311
|
-
const body =
|
|
74312
|
-
const claimedEpoch =
|
|
74631
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74632
|
+
const claimedEpoch = numberOf2(body, "worker_epoch");
|
|
74313
74633
|
if (claimedEpoch !== void 0 && claimedEpoch !== RC_SELF_HOST_WORKER_EPOCH) {
|
|
74314
74634
|
await epochStale(response);
|
|
74315
74635
|
return;
|
|
74316
74636
|
}
|
|
74317
|
-
const status =
|
|
74637
|
+
const status = nonEmptyString3(body, "worker_status");
|
|
74318
74638
|
if (status !== void 0) {
|
|
74319
74639
|
session.workerStatus = status;
|
|
74320
74640
|
}
|
|
74321
|
-
if (
|
|
74641
|
+
if (isRecord6(body?.external_metadata)) {
|
|
74322
74642
|
session.externalMetadata = body.external_metadata;
|
|
74323
74643
|
}
|
|
74324
74644
|
await answerJson2(response, HTTP_STATUS.ok, {});
|
|
@@ -74335,8 +74655,8 @@ data: ${JSON.stringify(envelope)}
|
|
|
74335
74655
|
return;
|
|
74336
74656
|
}
|
|
74337
74657
|
if (workerTail === "events" && method === "POST") {
|
|
74338
|
-
const body =
|
|
74339
|
-
const claimedEpoch =
|
|
74658
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74659
|
+
const claimedEpoch = numberOf2(body, "worker_epoch");
|
|
74340
74660
|
if (claimedEpoch !== void 0 && claimedEpoch !== RC_SELF_HOST_WORKER_EPOCH) {
|
|
74341
74661
|
await epochStale(response);
|
|
74342
74662
|
return;
|
|
@@ -74348,7 +74668,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
74348
74668
|
}
|
|
74349
74669
|
const results = [];
|
|
74350
74670
|
for (const event of events) {
|
|
74351
|
-
if (!
|
|
74671
|
+
if (!isRecord6(event) || !isRecord6(event.payload)) {
|
|
74352
74672
|
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a batch is an object carrying one payload object" } });
|
|
74353
74673
|
return;
|
|
74354
74674
|
}
|
|
@@ -74369,8 +74689,8 @@ data: ${JSON.stringify(envelope)}
|
|
|
74369
74689
|
return;
|
|
74370
74690
|
}
|
|
74371
74691
|
if (workerTail === "internal-events" && method === "POST") {
|
|
74372
|
-
const body =
|
|
74373
|
-
const claimedEpoch =
|
|
74692
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74693
|
+
const claimedEpoch = numberOf2(body, "worker_epoch");
|
|
74374
74694
|
if (claimedEpoch !== void 0 && claimedEpoch !== RC_SELF_HOST_WORKER_EPOCH) {
|
|
74375
74695
|
await epochStale(response);
|
|
74376
74696
|
return;
|
|
@@ -74381,19 +74701,26 @@ data: ${JSON.stringify(envelope)}
|
|
|
74381
74701
|
return;
|
|
74382
74702
|
}
|
|
74383
74703
|
for (const event of events) {
|
|
74384
|
-
if (
|
|
74385
|
-
session.internalEvents.push({
|
|
74704
|
+
if (isRecord6(event)) {
|
|
74705
|
+
session.internalEvents.push({ eventId: deps.newUuid(), body: event });
|
|
74386
74706
|
}
|
|
74387
74707
|
}
|
|
74388
74708
|
await answerJson2(response, HTTP_STATUS.ok, {});
|
|
74389
74709
|
return;
|
|
74390
74710
|
}
|
|
74391
74711
|
if (workerTail === "internal-events" && method === "GET") {
|
|
74392
|
-
const
|
|
74393
|
-
|
|
74394
|
-
|
|
74395
|
-
|
|
74396
|
-
|
|
74712
|
+
const query = new URL(request7.url, "http://127.0.0.1").searchParams;
|
|
74713
|
+
if (query.get("session_agent_id") !== null || query.get("subagents") !== null) {
|
|
74714
|
+
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "this surface keeps one internal-events channel per session, so an agent-scoped read has no subset to serve" } });
|
|
74715
|
+
return;
|
|
74716
|
+
}
|
|
74717
|
+
const page = pageOfRcChannel(request7.url, session.internalEvents, (event) => event.eventId, (event) => ({ event_id: event.eventId, payload: event.body }));
|
|
74718
|
+
if ("error" in page) {
|
|
74719
|
+
const anchorUnknown = query.get("after_event_id") !== null && page.error.startsWith("the anchor names an event id");
|
|
74720
|
+
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: anchorUnknown ? "after_event_id_not_found" : "invalid_request_error", message: page.error } });
|
|
74721
|
+
return;
|
|
74722
|
+
}
|
|
74723
|
+
await answerJson2(response, HTTP_STATUS.ok, page);
|
|
74397
74724
|
return;
|
|
74398
74725
|
}
|
|
74399
74726
|
if (workerTail === "diagnostics" && method === "POST") {
|
|
@@ -74402,8 +74729,8 @@ data: ${JSON.stringify(envelope)}
|
|
|
74402
74729
|
return;
|
|
74403
74730
|
}
|
|
74404
74731
|
if (workerTail === "web-fetch" && method === "POST") {
|
|
74405
|
-
const body =
|
|
74406
|
-
const target =
|
|
74732
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74733
|
+
const target = nonEmptyString3(body, "url");
|
|
74407
74734
|
if (target === void 0) {
|
|
74408
74735
|
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "a worker web-fetch carries one url" } });
|
|
74409
74736
|
return;
|
|
@@ -74425,8 +74752,8 @@ data: ${JSON.stringify(envelope)}
|
|
|
74425
74752
|
return;
|
|
74426
74753
|
}
|
|
74427
74754
|
if (workerTail === "web-search" && method === "POST") {
|
|
74428
|
-
const body =
|
|
74429
|
-
const query =
|
|
74755
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74756
|
+
const query = nonEmptyString3(body, "query");
|
|
74430
74757
|
if (query === void 0) {
|
|
74431
74758
|
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "a worker web-search carries one query" } });
|
|
74432
74759
|
return;
|
|
@@ -74437,7 +74764,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
74437
74764
|
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "the domain filters of a worker web-search are string arrays" } });
|
|
74438
74765
|
return;
|
|
74439
74766
|
}
|
|
74440
|
-
const searchProfile =
|
|
74767
|
+
const searchProfile = nonEmptyString3(body, "search_profile");
|
|
74441
74768
|
const backend = deps.webSearch;
|
|
74442
74769
|
if (backend === void 0) {
|
|
74443
74770
|
deps.log?.(`rc selfhost ${session.id}: worker web-search of "${query}" refused: no search backend serves this door`);
|
|
@@ -74462,7 +74789,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
74462
74789
|
return;
|
|
74463
74790
|
}
|
|
74464
74791
|
if (tail === "events" && method === "POST") {
|
|
74465
|
-
const body =
|
|
74792
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74466
74793
|
const events = body?.events;
|
|
74467
74794
|
if (!Array.isArray(events) || events.length === 0 || events.length > RC_SELF_HOST_MAX_BATCH_EVENTS) {
|
|
74468
74795
|
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: `a client event write is a non-empty array of at most ${String(RC_SELF_HOST_MAX_BATCH_EVENTS)} events` } });
|
|
@@ -74470,7 +74797,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
74470
74797
|
}
|
|
74471
74798
|
const results = [];
|
|
74472
74799
|
for (const event of events) {
|
|
74473
|
-
if (!
|
|
74800
|
+
if (!isRecord6(event) || !isRecord6(event.payload)) {
|
|
74474
74801
|
await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a write is an object carrying one payload object" } });
|
|
74475
74802
|
return;
|
|
74476
74803
|
}
|
|
@@ -74482,26 +74809,14 @@ data: ${JSON.stringify(envelope)}
|
|
|
74482
74809
|
return;
|
|
74483
74810
|
}
|
|
74484
74811
|
if (tail === "events" && method === "GET") {
|
|
74485
|
-
await answerJson2(response, HTTP_STATUS.ok, { data: session.events.map((event) => ({ event_id: event.eventId, event_type:
|
|
74812
|
+
await answerJson2(response, HTTP_STATUS.ok, { data: session.events.map((event) => ({ event_id: event.eventId, event_type: nonEmptyString3(event.payload, "type") ?? "event", sequence_num: event.sequenceNum, source: event.source, payload: event.payload, created_at: event.createdAt })) });
|
|
74486
74813
|
return;
|
|
74487
74814
|
}
|
|
74488
74815
|
if (tail === "events/stream" && method === "GET") {
|
|
74489
74816
|
await holdStream(session, "clientStreams", () => true, request7, response);
|
|
74490
74817
|
return;
|
|
74491
74818
|
}
|
|
74492
|
-
if (
|
|
74493
|
-
await readBody3(request7.body, CONTROL_BODY_CAP_BYTES);
|
|
74494
|
-
await answerJson2(response, HTTP_STATUS.ok, { refresh_after_seconds: RC_PRESENCE_REFRESH_SECONDS });
|
|
74495
|
-
return;
|
|
74496
|
-
}
|
|
74497
|
-
if (tail === "mark_read" && method === "POST") {
|
|
74498
|
-
await readBody3(request7.body, CONTROL_BODY_CAP_BYTES);
|
|
74499
|
-
await answerJson2(response, HTTP_STATUS.ok, {});
|
|
74500
|
-
return;
|
|
74501
|
-
}
|
|
74502
|
-
if (tail === "teleport-events" && method === "POST") {
|
|
74503
|
-
await readBody3(request7.body, CONTROL_BODY_CAP_BYTES);
|
|
74504
|
-
await answerJson2(response, HTTP_STATUS.ok, {});
|
|
74819
|
+
if (await serveRcClientChannels({ request: request7, response, session, answerJson: answerJson2, readBody: readBody3, publish, sweep, now: deps.now, presenceRefreshSeconds: RC_PRESENCE_REFRESH_SECONDS, ...deps.log === void 0 ? {} : { log: deps.log } }, tail, method, RC_SELF_HOST_MAX_BATCH_EVENTS)) {
|
|
74505
74820
|
return;
|
|
74506
74821
|
}
|
|
74507
74822
|
await answerJson2(response, HTTP_STATUS.notFound, { type: "error", error: { type: "api_error", message: `the self-hosted Remote Control surface serves no path "${tail}"` } });
|
|
@@ -74518,17 +74833,8 @@ data: ${JSON.stringify(envelope)}
|
|
|
74518
74833
|
await noCredential(response);
|
|
74519
74834
|
return;
|
|
74520
74835
|
}
|
|
74521
|
-
if (pathname === RC_COMPAT_SESSIONS_PATH) {
|
|
74522
|
-
|
|
74523
|
-
await answerJson2(response, HTTP_STATUS.methodNotAllowed, { type: "error", error: { type: "api_error", message: "the compatibility session list is a GET" } });
|
|
74524
|
-
return;
|
|
74525
|
-
}
|
|
74526
|
-
const listRefusal = credentialRefusal(request7.headers);
|
|
74527
|
-
if (listRefusal !== void 0) {
|
|
74528
|
-
await unauthorized(response, listRefusal);
|
|
74529
|
-
return;
|
|
74530
|
-
}
|
|
74531
|
-
await answerJson2(response, HTTP_STATUS.ok, { data: [] });
|
|
74836
|
+
if (pathname === RC_COMPAT_SESSIONS_PATH || pathname.startsWith(`${RC_COMPAT_SESSIONS_PATH}/`)) {
|
|
74837
|
+
await serveRcCompatSessions({ request: request7, response, sessions, answerJson: answerJson2, readBody: readBody3, credentialRefusal, unauthorized, now: deps.now, ...deps.log === void 0 ? {} : { log: deps.log } }, pathname, RC_COMPAT_SESSIONS_PATH);
|
|
74532
74838
|
return;
|
|
74533
74839
|
}
|
|
74534
74840
|
if (pathname !== RC_SESSIONS_PATH_PREFIX2 && !pathname.startsWith(`${RC_SESSIONS_PATH_PREFIX2}/`)) {
|
|
@@ -74542,11 +74848,11 @@ data: ${JSON.stringify(envelope)}
|
|
|
74542
74848
|
await unauthorized(response, createRefusal);
|
|
74543
74849
|
return;
|
|
74544
74850
|
}
|
|
74545
|
-
const body =
|
|
74851
|
+
const body = parseJsonObject3(await readBody3(request7.body, CONTROL_BODY_CAP_BYTES));
|
|
74546
74852
|
const session = {
|
|
74547
74853
|
id: `${RC_SESSION_ID_PREFIX2}${deps.newUuid()}`,
|
|
74548
74854
|
createdAt: deps.now(),
|
|
74549
|
-
title:
|
|
74855
|
+
title: nonEmptyString3(body, "title"),
|
|
74550
74856
|
workerJwts: /* @__PURE__ */ new Set(),
|
|
74551
74857
|
sequenceNum: 0,
|
|
74552
74858
|
events: [],
|
|
@@ -74554,6 +74860,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
74554
74860
|
workerStreams: /* @__PURE__ */ new Set(),
|
|
74555
74861
|
clientStreams: /* @__PURE__ */ new Set(),
|
|
74556
74862
|
internalEvents: [],
|
|
74863
|
+
clients: /* @__PURE__ */ new Map(),
|
|
74557
74864
|
workerStatus: void 0,
|
|
74558
74865
|
externalMetadata: void 0,
|
|
74559
74866
|
lastTrafficAt: deps.now()
|
|
@@ -74598,7 +74905,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
74598
74905
|
const pathname = new URL(request7.url ?? "/", "http://127.0.0.1").pathname;
|
|
74599
74906
|
if (host === RC_SELF_HOST_OAUTH_HOST) {
|
|
74600
74907
|
if (method === "POST" && pathname === "/v1/oauth/token") {
|
|
74601
|
-
const body =
|
|
74908
|
+
const body = parseJsonObject3(await readBody3(request7, CONTROL_BODY_CAP_BYTES));
|
|
74602
74909
|
const record2 = deps.credentialRecord();
|
|
74603
74910
|
if (record2 === void 0) {
|
|
74604
74911
|
answerServerJson(response, HTTP_SERVICE_UNAVAILABLE, { error: "the front door's self-hosted Remote Control surface is on but no credential has been minted for it" });
|
|
@@ -74683,7 +74990,7 @@ var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
|
|
|
74683
74990
|
var RC_SELF_HOST_RECORD_FILE = "credential.json";
|
|
74684
74991
|
var SELF_HOST_EMAIL = "selfhost@agent-shim.invalid";
|
|
74685
74992
|
var SELF_HOST_SUBSCRIPTION_TYPE = "max";
|
|
74686
|
-
function
|
|
74993
|
+
function isRecord7(value2) {
|
|
74687
74994
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
74688
74995
|
}
|
|
74689
74996
|
function readJsonObject(fs20, file2) {
|
|
@@ -74697,7 +75004,7 @@ function readJsonObject(fs20, file2) {
|
|
|
74697
75004
|
} catch {
|
|
74698
75005
|
return void 0;
|
|
74699
75006
|
}
|
|
74700
|
-
return
|
|
75007
|
+
return isRecord7(parsed) ? parsed : void 0;
|
|
74701
75008
|
}
|
|
74702
75009
|
function readRcSelfHostRecord(fs20, frontdoorDir) {
|
|
74703
75010
|
const parsed = readJsonObject(fs20, import_node_path34.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
|
|
@@ -74721,7 +75028,7 @@ function mintRcSelfHostCredential(deps) {
|
|
|
74721
75028
|
const recordFile = import_node_path34.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
|
|
74722
75029
|
const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
|
|
74723
75030
|
const existingCredentials = readJsonObject(deps.fs, credentialsFile);
|
|
74724
|
-
const existingOauth =
|
|
75031
|
+
const existingOauth = isRecord7(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
|
|
74725
75032
|
const existingToken = typeof existingOauth?.accessToken === "string" && existingOauth.accessToken !== "" ? existingOauth.accessToken : void 0;
|
|
74726
75033
|
const existingIsOwn = existingToken !== void 0 && previousRecord?.accessToken === existingToken;
|
|
74727
75034
|
if (existingToken !== void 0 && !existingIsOwn && !deps.force) {
|
|
@@ -74738,7 +75045,7 @@ function mintRcSelfHostCredential(deps) {
|
|
|
74738
75045
|
deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
|
|
74739
75046
|
`);
|
|
74740
75047
|
const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
|
|
74741
|
-
const existingBlock = (value2) =>
|
|
75048
|
+
const existingBlock = (value2) => isRecord7(value2) ? value2 : {};
|
|
74742
75049
|
deps.fs.writeFilePrivate(claudeJsonFile, `${JSON.stringify({
|
|
74743
75050
|
...claudeJson,
|
|
74744
75051
|
oauthAccount: {
|
|
@@ -74816,9 +75123,54 @@ function formatRcPendingList(pending) {
|
|
|
74816
75123
|
function eventExcerpt(text2) {
|
|
74817
75124
|
return text2.length <= RC_PENDING_SUMMARY_EXCERPT_CHARS ? text2 : `${text2.slice(0, RC_PENDING_SUMMARY_EXCERPT_CHARS)}...`;
|
|
74818
75125
|
}
|
|
75126
|
+
var PERCENT_SCALE = 100;
|
|
75127
|
+
var MS_PER_SECOND8 = 1e3;
|
|
75128
|
+
function percentOf(fraction) {
|
|
75129
|
+
return `${String(Math.round(fraction * PERCENT_SCALE))}%`;
|
|
75130
|
+
}
|
|
75131
|
+
function resetInstantOf(epochSeconds) {
|
|
75132
|
+
return new Date(epochSeconds * MS_PER_SECOND8).toISOString();
|
|
75133
|
+
}
|
|
75134
|
+
function formatRcRateLimitInfo(info) {
|
|
75135
|
+
const parts = [info.status];
|
|
75136
|
+
if (info.rateLimitType !== void 0) {
|
|
75137
|
+
parts.push(info.rateLimitType);
|
|
75138
|
+
}
|
|
75139
|
+
if (info.utilization !== void 0) {
|
|
75140
|
+
parts.push(percentOf(info.utilization));
|
|
75141
|
+
}
|
|
75142
|
+
if (info.resetsAt !== void 0) {
|
|
75143
|
+
parts.push(`resets ${resetInstantOf(info.resetsAt)}`);
|
|
75144
|
+
}
|
|
75145
|
+
const windows = [];
|
|
75146
|
+
for (const name of ["five_hour", "seven_day", "seven_day_overage_included"]) {
|
|
75147
|
+
const window = info.unifiedWindows?.[name];
|
|
75148
|
+
if (window === void 0) {
|
|
75149
|
+
continue;
|
|
75150
|
+
}
|
|
75151
|
+
const bits = [];
|
|
75152
|
+
if (window.utilization !== void 0) {
|
|
75153
|
+
bits.push(percentOf(window.utilization));
|
|
75154
|
+
}
|
|
75155
|
+
if (window.resetsAt !== void 0) {
|
|
75156
|
+
bits.push(`resets ${resetInstantOf(window.resetsAt)}`);
|
|
75157
|
+
}
|
|
75158
|
+
windows.push(bits.length === 0 ? name : `${name} ${bits.join(" ")}`);
|
|
75159
|
+
}
|
|
75160
|
+
if (windows.length > 0) {
|
|
75161
|
+
parts.push(`windows ${windows.join(", ")}`);
|
|
75162
|
+
}
|
|
75163
|
+
if (info.isUsingOverage === true) {
|
|
75164
|
+
parts.push("overage in use");
|
|
75165
|
+
} else if (info.overageStatus !== void 0) {
|
|
75166
|
+
parts.push(`overage ${info.overageStatus}`);
|
|
75167
|
+
}
|
|
75168
|
+
return parts.join(" ");
|
|
75169
|
+
}
|
|
74819
75170
|
function formatRcStreamEvent(event) {
|
|
74820
75171
|
const { envelope } = event;
|
|
74821
|
-
const
|
|
75172
|
+
const rateLimit = rcRateLimitInfoOf(event);
|
|
75173
|
+
const sketch = rateLimit !== void 0 ? ` ${formatRcRateLimitInfo(rateLimit)}` : envelope.payload === void 0 ? "" : ` ${eventExcerpt(JSON.stringify(envelope.payload))}`;
|
|
74822
75174
|
return `${event.session} ${envelope.event_type} sequence_num ${String(envelope.sequence_num)} source ${envelope.source}${sketch}`;
|
|
74823
75175
|
}
|
|
74824
75176
|
function formatRcSelfHostMint(result) {
|
|
@@ -75038,7 +75390,13 @@ function registerRcCommand(frontdoor, paths) {
|
|
|
75038
75390
|
["agent-shim frontdoor rc mcp-oauth-callback-url --session cse_00000000-0000-4000-8000-000000000000 --server github --callback-url https://example.com/oauth/callback?code=x"]
|
|
75039
75391
|
);
|
|
75040
75392
|
withExamples(
|
|
75041
|
-
rc.command("
|
|
75393
|
+
rc.command("teleport").description("Send one teleport marker into an observed session over the teleport-events channel, the write half the cloud UI's ultrapan path owns on the real service. The marker rides the SDK user-message shape, the line the teleport relay anchors on.").requiredOption("--session <id>", "The cse_ session id, as `frontdoor rc list` shows it.").requiredOption("--marker <text>", "The marker text, the string content the teleport relay anchors on.").option("--json", "Print the delivery result as JSON.").action(async (options) => {
|
|
75394
|
+
reportControlWrite(`teleported a marker into the session`, options.session, await frontDoorRcControlFromState(realFarmFs, paths).teleport(options.session, options.marker), options.json, { marker: options.marker });
|
|
75395
|
+
}),
|
|
75396
|
+
['agent-shim frontdoor rc teleport --session cse_00000000-0000-4000-8000-000000000000 --marker "__ULTRAPAN_TELEPORT_LOCAL__"']
|
|
75397
|
+
);
|
|
75398
|
+
withExamples(
|
|
75399
|
+
rc.command("watch").description("Print the observed sessions' client read stream events as they arrive, the approvals the door's held stream receives above all, with each rate_limit_event rendered as the account's quota state. Read-only, until Ctrl-C leaves.").argument("[session]", "One cse_ session id, as `frontdoor rc list` shows it; every observed session when omitted.").option("--json", "Print each event as one JSON line as it arrives.").action(async (session, options) => {
|
|
75042
75400
|
const client = frontDoorRcApiFromState(realFarmFs, paths);
|
|
75043
75401
|
const leave = new AbortController();
|
|
75044
75402
|
const onInterrupt = () => {
|
|
@@ -75096,11 +75454,11 @@ var import_node_path35 = __toESM(require("node:path"), 1);
|
|
|
75096
75454
|
function isSafeSessionId(sessionId) {
|
|
75097
75455
|
return /^[A-Za-z0-9_-]+$/.test(sessionId);
|
|
75098
75456
|
}
|
|
75099
|
-
function
|
|
75457
|
+
function isRecord8(value2) {
|
|
75100
75458
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
75101
75459
|
}
|
|
75102
75460
|
function credentialOfJson(parsed) {
|
|
75103
|
-
if (!
|
|
75461
|
+
if (!isRecord8(parsed)) {
|
|
75104
75462
|
return void 0;
|
|
75105
75463
|
}
|
|
75106
75464
|
const { authorization, anthropicVersion, anthropicClientPlatform } = parsed;
|
|
@@ -75130,7 +75488,7 @@ function createRcCredentialStore(fs20, dir) {
|
|
|
75130
75488
|
} catch {
|
|
75131
75489
|
return void 0;
|
|
75132
75490
|
}
|
|
75133
|
-
return
|
|
75491
|
+
return isRecord8(parsed) ? parsed : void 0;
|
|
75134
75492
|
};
|
|
75135
75493
|
return {
|
|
75136
75494
|
read: (sessionId) => {
|
|
@@ -75244,12 +75602,61 @@ function sketch(value, cap) {
|
|
|
75244
75602
|
return text.length > cap ? text.slice(0, cap) + '...' : text;
|
|
75245
75603
|
}
|
|
75246
75604
|
|
|
75247
|
-
//
|
|
75605
|
+
// One utilization fraction as a whole percentage, the same rounding the CLI's own watch line applies.
|
|
75606
|
+
function percentOf(fraction) { return String(Math.round(fraction * 100)) + '%'; }
|
|
75607
|
+
|
|
75608
|
+
// The reset instant a rate-limit payload states (unix epoch seconds) as an ISO instant; no countdown is derived from it, because a ticking derivation would claim a freshness the event stream never promised.
|
|
75609
|
+
function resetInstantOf(epochSeconds) { return new Date(epochSeconds * 1000).toISOString(); }
|
|
75610
|
+
|
|
75611
|
+
// Whether one rate-limit payload is readable, narrowed the same way the door's live usage state narrows it: the event type and a rate_limit_info object.
|
|
75612
|
+
function rateLimitInfoOf(payload) {
|
|
75613
|
+
if (payload === undefined || payload === null || typeof payload !== 'object' || payload.type !== 'rate_limit_event') { return undefined; }
|
|
75614
|
+
var info = payload.rate_limit_info;
|
|
75615
|
+
if (info === undefined || info === null || typeof info !== 'object' || typeof info.status !== 'string') { return undefined; }
|
|
75616
|
+
return info;
|
|
75617
|
+
}
|
|
75618
|
+
|
|
75619
|
+
// One rate-limit payload's facts as the quota summary the feed and the header render: the limiting window's status and utilisation, each subscription window, and the overage state, every value the payload's own words.
|
|
75620
|
+
function quotaSummary(info) {
|
|
75621
|
+
var parts = [info.status];
|
|
75622
|
+
if (info.rateLimitType !== undefined) { parts.push(info.rateLimitType); }
|
|
75623
|
+
if (typeof info.utilization === 'number') { parts.push(percentOf(info.utilization)); }
|
|
75624
|
+
if (typeof info.resetsAt === 'number') { parts.push('resets ' + resetInstantOf(info.resetsAt)); }
|
|
75625
|
+
if (info.unifiedWindows !== undefined && info.unifiedWindows !== null && typeof info.unifiedWindows === 'object') {
|
|
75626
|
+
var names = ['five_hour', 'seven_day', 'seven_day_overage_included'];
|
|
75627
|
+
var windows = [];
|
|
75628
|
+
for (var i = 0; i < names.length; i++) {
|
|
75629
|
+
var window = info.unifiedWindows[names[i]];
|
|
75630
|
+
if (window === undefined || window === null) { continue; }
|
|
75631
|
+
var bits = [];
|
|
75632
|
+
if (typeof window.utilization === 'number') { bits.push(percentOf(window.utilization)); }
|
|
75633
|
+
if (typeof window.resetsAt === 'number') { bits.push('resets ' + resetInstantOf(window.resetsAt)); }
|
|
75634
|
+
windows.push(bits.length === 0 ? names[i] : names[i] + ' ' + bits.join(' '));
|
|
75635
|
+
}
|
|
75636
|
+
if (windows.length > 0) { parts.push('windows ' + windows.join(', ')); }
|
|
75637
|
+
}
|
|
75638
|
+
if (info.isUsingOverage === true) { parts.push('overage in use'); }
|
|
75639
|
+
else if (typeof info.overageStatus === 'string') { parts.push('overage ' + info.overageStatus); }
|
|
75640
|
+
return parts.join(' ');
|
|
75641
|
+
}
|
|
75642
|
+
|
|
75643
|
+
// The header's quota text from the door's freshest live observation: the quota summary plus when the door observed it, or the plain statement that none has arrived yet.
|
|
75644
|
+
function quotaText(latest) {
|
|
75645
|
+
if (latest === undefined || latest === null) { return 'quota: not observed yet'; }
|
|
75646
|
+
var info = rateLimitInfoOf({ type: 'rate_limit_event', rate_limit_info: latest.rateLimit });
|
|
75647
|
+
if (info === undefined) { return 'quota: not readable'; }
|
|
75648
|
+
return 'quota: ' + quotaSummary(info) + ' observed ' + new Date(latest.observedAt).toLocaleTimeString();
|
|
75649
|
+
}
|
|
75650
|
+
|
|
75651
|
+
// The headline text of one Remote Control stream event: a rate-limit payload renders as its quota summary, the assistant and user payloads that carry a content array of text blocks render as their prose, everything else as its type plus a sketch.
|
|
75248
75652
|
function rcLine(event) {
|
|
75249
75653
|
var envelope = event.envelope;
|
|
75250
75654
|
var payload = envelope.payload;
|
|
75251
75655
|
var headline = '';
|
|
75252
|
-
|
|
75656
|
+
var rateLimit = rateLimitInfoOf(payload);
|
|
75657
|
+
if (rateLimit !== undefined) {
|
|
75658
|
+
headline = quotaSummary(rateLimit);
|
|
75659
|
+
} else if (payload !== undefined && payload !== null && typeof payload === 'object' && Array.isArray(payload.content)) {
|
|
75253
75660
|
var parts = [];
|
|
75254
75661
|
for (var i = 0; i < payload.content.length; i++) {
|
|
75255
75662
|
var block = payload.content[i];
|
|
@@ -75378,6 +75785,13 @@ function refreshPending() {
|
|
|
75378
75785
|
rpc('rc/pending', ui !== null && ui.selected !== null ? { session: ui.selected } : {}).then(function (result) { renderPending(result.pending); }, authOrReport('rc/pending'));
|
|
75379
75786
|
}
|
|
75380
75787
|
|
|
75788
|
+
// The header's quota span, fed by the door's live read on the same refresh cycle as the session and pending lists: the freshest rate-limit observation any session's stream has filed, with its observation time so its freshness reads at a glance.
|
|
75789
|
+
function refreshQuota() {
|
|
75790
|
+
rpc('usage/live', {}).then(function (result) {
|
|
75791
|
+
if (ui !== null) { ui.quotaState.textContent = quotaText(result.latest); }
|
|
75792
|
+
}, authOrReport('usage/live'));
|
|
75793
|
+
}
|
|
75794
|
+
|
|
75381
75795
|
// The one error path every call shares: a 401 means this token is not this generation's, so the page says so and asks for it again; anything else is reported in the feed.
|
|
75382
75796
|
function authOrReport(what) {
|
|
75383
75797
|
return function (error) {
|
|
@@ -75465,11 +75879,12 @@ function startPage(heldToken) {
|
|
|
75465
75879
|
promptTarget: document.getElementById('prompt-target'),
|
|
75466
75880
|
send: document.getElementById('send'),
|
|
75467
75881
|
streamState: document.getElementById('stream-state'),
|
|
75882
|
+
quotaState: document.getElementById('quota-state'),
|
|
75468
75883
|
selected: null,
|
|
75469
75884
|
};
|
|
75470
75885
|
document.getElementById('token-form').classList.add('hidden');
|
|
75471
75886
|
ui.main.classList.remove('hidden');
|
|
75472
|
-
document.getElementById('refresh').addEventListener('click', function () { refreshSessions(); refreshPending(); });
|
|
75887
|
+
document.getElementById('refresh').addEventListener('click', function () { refreshSessions(); refreshPending(); refreshQuota(); });
|
|
75473
75888
|
document.getElementById('send').addEventListener('click', sendPrompt);
|
|
75474
75889
|
document.getElementById('source-filter').addEventListener('change', function () { runFeed(); });
|
|
75475
75890
|
ui.prompt.addEventListener('keydown', function (event) {
|
|
@@ -75477,7 +75892,8 @@ function startPage(heldToken) {
|
|
|
75477
75892
|
});
|
|
75478
75893
|
refreshSessions();
|
|
75479
75894
|
refreshPending();
|
|
75480
|
-
|
|
75895
|
+
refreshQuota();
|
|
75896
|
+
window.setInterval(function () { refreshSessions(); refreshPending(); refreshQuota(); }, 4000);
|
|
75481
75897
|
runFeed();
|
|
75482
75898
|
document.getElementById('door-state').textContent = 'connected';
|
|
75483
75899
|
}
|
|
@@ -75556,6 +75972,7 @@ var RC_CLIENT_PAGE_HTML = `<!doctype html>
|
|
|
75556
75972
|
<h1>agent-shim Remote Control</h1>
|
|
75557
75973
|
<span class="state" id="door-state">connecting</span>
|
|
75558
75974
|
<span class="state" id="stream-state"></span>
|
|
75975
|
+
<span class="state" id="quota-state">quota: not observed yet</span>
|
|
75559
75976
|
</header>
|
|
75560
75977
|
<div id="token-form">
|
|
75561
75978
|
<h2>This door's control token</h2>
|
|
@@ -75694,7 +76111,7 @@ function createSseParser() {
|
|
|
75694
76111
|
}
|
|
75695
76112
|
};
|
|
75696
76113
|
}
|
|
75697
|
-
function
|
|
76114
|
+
function isRecord9(value2) {
|
|
75698
76115
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
75699
76116
|
}
|
|
75700
76117
|
function sequenceNumOf(value2) {
|
|
@@ -75716,7 +76133,7 @@ function parseRcStreamEnvelope(parsed) {
|
|
|
75716
76133
|
} catch {
|
|
75717
76134
|
return void 0;
|
|
75718
76135
|
}
|
|
75719
|
-
if (!
|
|
76136
|
+
if (!isRecord9(data)) {
|
|
75720
76137
|
return void 0;
|
|
75721
76138
|
}
|
|
75722
76139
|
const eventType = data.event_type;
|
|
@@ -75799,9 +76216,26 @@ function createRcStreamHub(deps) {
|
|
|
75799
76216
|
}
|
|
75800
76217
|
return headers;
|
|
75801
76218
|
};
|
|
76219
|
+
let receiptFailureLogged = false;
|
|
76220
|
+
const sendReceipt = (attachment, headers, eventId) => {
|
|
76221
|
+
if (eventId === void 0) {
|
|
76222
|
+
return;
|
|
76223
|
+
}
|
|
76224
|
+
deps.dial.markRead(attachment.sessionId, headers, eventId).then(
|
|
76225
|
+
() => {
|
|
76226
|
+
receiptFailureLogged = false;
|
|
76227
|
+
},
|
|
76228
|
+
(error62) => {
|
|
76229
|
+
if (!receiptFailureLogged) {
|
|
76230
|
+
receiptFailureLogged = true;
|
|
76231
|
+
deps.log?.(`rc stream ${attachment.sessionId}: the read receipt for event ${eventId} could not be sent (${error62 instanceof Error ? error62.message : String(error62)}); further receipt failures stay quiet until one lands`);
|
|
76232
|
+
}
|
|
76233
|
+
}
|
|
76234
|
+
);
|
|
76235
|
+
};
|
|
75802
76236
|
const attempt = async (attachment, credential) => {
|
|
75803
76237
|
const headers = streamHeaders(credential);
|
|
75804
|
-
const presence = await deps.dial.announcePresence(attachment.sessionId, headers, attachment.clientId);
|
|
76238
|
+
const presence = await deps.dial.announcePresence(attachment.sessionId, headers, attachment.clientId, false);
|
|
75805
76239
|
if (presence.status === HTTP_STATUS.unauthorized) {
|
|
75806
76240
|
return "unauthorized";
|
|
75807
76241
|
}
|
|
@@ -75821,6 +76255,7 @@ function createRcStreamHub(deps) {
|
|
|
75821
76255
|
const parser = createSseParser();
|
|
75822
76256
|
for await (const chunk of answer.chunks) {
|
|
75823
76257
|
attachment.controller.signal.throwIfAborted();
|
|
76258
|
+
let lastEventId;
|
|
75824
76259
|
for (const parsed of parser.write(Buffer.from(chunk).toString("utf8"))) {
|
|
75825
76260
|
const envelope = parseRcStreamEnvelope(parsed);
|
|
75826
76261
|
if (envelope === void 0) {
|
|
@@ -75828,10 +76263,21 @@ function createRcStreamHub(deps) {
|
|
|
75828
76263
|
}
|
|
75829
76264
|
deps.fileStreamEvent(attachment.sessionId, envelope);
|
|
75830
76265
|
deps.fanout.publish({ session: attachment.sessionId, envelope });
|
|
76266
|
+
if (typeof envelope.event_id === "string" && envelope.event_type !== "mark_read") {
|
|
76267
|
+
lastEventId = envelope.event_id;
|
|
76268
|
+
}
|
|
75831
76269
|
}
|
|
76270
|
+
sendReceipt(attachment, headers, lastEventId);
|
|
75832
76271
|
}
|
|
75833
76272
|
return "dropped";
|
|
75834
76273
|
};
|
|
76274
|
+
const clearPresence = (attachment, headers) => {
|
|
76275
|
+
if (headers === void 0) {
|
|
76276
|
+
return;
|
|
76277
|
+
}
|
|
76278
|
+
void deps.dial.announcePresence(attachment.sessionId, headers, attachment.clientId, true).catch(() => {
|
|
76279
|
+
});
|
|
76280
|
+
};
|
|
75835
76281
|
const runLoop = async (attachment) => {
|
|
75836
76282
|
let retriedUnauthorized = false;
|
|
75837
76283
|
for (; ; ) {
|
|
@@ -75843,6 +76289,7 @@ function createRcStreamHub(deps) {
|
|
|
75843
76289
|
if (!live || credential?.authorization === void 0) {
|
|
75844
76290
|
deps.log?.(`rc stream ${attachment.sessionId}: the attachment ended (${live ? "the session's client credential is no longer known" : "the tracker gave up on the session"})`);
|
|
75845
76291
|
persistCursor(attachment.sessionId);
|
|
76292
|
+
clearPresence(attachment, credential === void 0 ? void 0 : streamHeaders(credential));
|
|
75846
76293
|
if (attachments.get(attachment.sessionId) === attachment) {
|
|
75847
76294
|
attachments.delete(attachment.sessionId);
|
|
75848
76295
|
}
|
|
@@ -75905,6 +76352,8 @@ function createRcStreamHub(deps) {
|
|
|
75905
76352
|
close: () => {
|
|
75906
76353
|
for (const attachment of attachments.values()) {
|
|
75907
76354
|
persistCursor(attachment.sessionId);
|
|
76355
|
+
const credential = deps.credentialOf(attachment.sessionId);
|
|
76356
|
+
clearPresence(attachment, credential?.authorization === void 0 ? void 0 : streamHeaders(credential));
|
|
75908
76357
|
attachment.stop();
|
|
75909
76358
|
}
|
|
75910
76359
|
attachments.clear();
|
|
@@ -75972,7 +76421,7 @@ var ProviderQuotaError = class extends Error {
|
|
|
75972
76421
|
this.name = "ProviderQuotaError";
|
|
75973
76422
|
}
|
|
75974
76423
|
};
|
|
75975
|
-
var
|
|
76424
|
+
var MS_PER_SECOND9 = 1e3;
|
|
75976
76425
|
var SECONDS_PER_HOUR = 3600;
|
|
75977
76426
|
var HOURS_PER_DAY3 = 24;
|
|
75978
76427
|
var DAYS_PER_MONTH = 30;
|
|
@@ -75984,8 +76433,8 @@ var ZAI_QUOTA_URL = `https://${ZAI_HOST}/api/monitor/usage/quota/limit`;
|
|
|
75984
76433
|
var ZAI_UNIT_HOURS = 3;
|
|
75985
76434
|
var ZAI_UNIT_MONTHS = 5;
|
|
75986
76435
|
var ZAI_UNIT_MS = /* @__PURE__ */ new Map([
|
|
75987
|
-
[ZAI_UNIT_HOURS, SECONDS_PER_HOUR *
|
|
75988
|
-
[ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY3 * SECONDS_PER_HOUR *
|
|
76436
|
+
[ZAI_UNIT_HOURS, SECONDS_PER_HOUR * MS_PER_SECOND9],
|
|
76437
|
+
[ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND9]
|
|
75989
76438
|
]);
|
|
75990
76439
|
var ZAI_MEASURES = { TOKENS_LIMIT: "tokens", TIME_LIMIT: "tool-calls" };
|
|
75991
76440
|
var ZaiLimitSchema = external_exports.object({
|
|
@@ -76049,7 +76498,7 @@ var OPENROUTER_HOST = "openrouter.ai";
|
|
|
76049
76498
|
var OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
|
|
76050
76499
|
var OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
|
|
76051
76500
|
var HTTP_FORBIDDEN = 403;
|
|
76052
|
-
var MS_PER_DAY2 = HOURS_PER_DAY3 * SECONDS_PER_HOUR *
|
|
76501
|
+
var MS_PER_DAY2 = HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND9;
|
|
76053
76502
|
var OpenRouterKeySchema = external_exports.object({
|
|
76054
76503
|
data: external_exports.object({
|
|
76055
76504
|
limit: external_exports.number().nonnegative().nullable(),
|
|
@@ -76292,6 +76741,7 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
76292
76741
|
const rcCredentialStore = createRcCredentialStore(realFarmFs, paths.frontdoorRcCredentialsDir);
|
|
76293
76742
|
const rcTracker = createRcSessionTracker({ now: () => Date.now(), idleMs: RC_IDLE_EXPIRY_MS, credentialStore: rcCredentialStore });
|
|
76294
76743
|
const doorEvents = createDoorEventHub();
|
|
76744
|
+
const rcLiveUsage = createRcLiveUsage({ now: () => Date.now(), hub: doorEvents });
|
|
76295
76745
|
const rcFanout = rcFanoutOnDoorHub(createRcEventFanout(), doorEvents);
|
|
76296
76746
|
const rcHub = createRcStreamHub({
|
|
76297
76747
|
now: () => Date.now(),
|
|
@@ -76392,7 +76842,11 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
76392
76842
|
const rcMcpReconnect = async (sessionId, serverName) => await reconnectRcSessionMcpServer(rcControlRequestDeps, sessionId, serverName);
|
|
76393
76843
|
const rcMcpAuthenticate = async (sessionId, serverName, redirectUri) => await authenticateRcSessionMcpServer(rcControlRequestDeps, sessionId, serverName, redirectUri);
|
|
76394
76844
|
const rcMcpOAuthCallbackUrl = async (sessionId, serverName, callbackUrl) => await submitRcSessionMcpOAuthCallbackUrl(rcControlRequestDeps, sessionId, serverName, callbackUrl);
|
|
76845
|
+
const rcTeleport = async (sessionId, marker) => await teleportRcSession(rcControlRequestDeps, sessionId, marker);
|
|
76395
76846
|
const controlDeps = {
|
|
76847
|
+
list: rcTracker.list,
|
|
76848
|
+
liveRateLimits: rcLiveUsage.liveOf,
|
|
76849
|
+
latestRateLimit: rcLiveUsage.latestOf,
|
|
76396
76850
|
usageSnapshots: () => listUsageSnapshots(realFarmFs, paths.usageSnapshotsDir),
|
|
76397
76851
|
usageSnapshotOf: (identity) => readUsageSnapshot(realFarmFs, paths.usageSnapshotsDir, identity),
|
|
76398
76852
|
now: () => Date.now(),
|
|
@@ -76409,11 +76863,10 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
76409
76863
|
},
|
|
76410
76864
|
log,
|
|
76411
76865
|
mintLeaf(authority, LOOPBACK_LEAF_NAMES, /* @__PURE__ */ new Date()),
|
|
76412
|
-
createRcControlHandler({ expectedToken: rcControlToken, list: rcTracker.list, statusOf: rcTracker.statusOf, pendingOf: rcTracker.pendingOf, inject: rcInject, answer: rcAnswer, interrupt: rcInterrupt, setModel: rcSetModel, setPermissionMode: rcSetPermissionMode, endSession: rcEndSession, getUsage: rcGetUsage, getContextUsage: rcGetContextUsage, readFile: rcReadFile, fileSuggestions: rcFileSuggestions, keepAlive: rcKeepAlive, mcpStatus: rcMcpStatus, mcpReconnect: rcMcpReconnect, mcpAuthenticate: rcMcpAuthenticate, mcpOAuthCallbackUrl: rcMcpOAuthCallbackUrl }),
|
|
76866
|
+
createRcControlHandler({ expectedToken: rcControlToken, list: rcTracker.list, statusOf: rcTracker.statusOf, pendingOf: rcTracker.pendingOf, inject: rcInject, answer: rcAnswer, interrupt: rcInterrupt, setModel: rcSetModel, setPermissionMode: rcSetPermissionMode, endSession: rcEndSession, getUsage: rcGetUsage, getContextUsage: rcGetContextUsage, readFile: rcReadFile, fileSuggestions: rcFileSuggestions, keepAlive: rcKeepAlive, mcpStatus: rcMcpStatus, mcpReconnect: rcMcpReconnect, mcpAuthenticate: rcMcpAuthenticate, mcpOAuthCallbackUrl: rcMcpOAuthCallbackUrl, teleport: rcTeleport }),
|
|
76413
76867
|
[
|
|
76414
76868
|
createDoorApiNodeHandler({
|
|
76415
76869
|
expectedToken: rcControlToken,
|
|
76416
|
-
list: rcTracker.list,
|
|
76417
76870
|
statusOf: rcTracker.statusOf,
|
|
76418
76871
|
pendingOf: rcTracker.pendingOf,
|
|
76419
76872
|
inject: rcInject,
|
|
@@ -76431,6 +76884,7 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
76431
76884
|
mcpReconnect: rcMcpReconnect,
|
|
76432
76885
|
mcpAuthenticate: rcMcpAuthenticate,
|
|
76433
76886
|
mcpOAuthCallbackUrl: rcMcpOAuthCallbackUrl,
|
|
76887
|
+
teleport: rcTeleport,
|
|
76434
76888
|
fanout: rcFanout,
|
|
76435
76889
|
...controlDeps,
|
|
76436
76890
|
events: doorEvents
|