agent-shim 8.5.2 → 8.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +744 -720
- package/dist/index.cjs +35 -9
- package/dist/index.mjs +35 -9
- package/dist/types/index.d.ts +9 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2732,7 +2732,7 @@ function readFrontDoorState(fs12, stateFile) {
|
|
|
2732
2732
|
}
|
|
2733
2733
|
function writeFrontDoorState(fs12, stateFile, state) {
|
|
2734
2734
|
fs12.mkdirp(import_node_path7.default.dirname(stateFile));
|
|
2735
|
-
fs12.
|
|
2735
|
+
fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
2736
2736
|
`);
|
|
2737
2737
|
}
|
|
2738
2738
|
function frontDoorOrigin(state) {
|
|
@@ -3629,6 +3629,11 @@ function singleHeader(headers, name) {
|
|
|
3629
3629
|
const value = headers[name];
|
|
3630
3630
|
return typeof value === "string" ? value : void 0;
|
|
3631
3631
|
}
|
|
3632
|
+
var OAUTH_AUTHORIZATION_PREFIX = "Bearer sk-ant-oat";
|
|
3633
|
+
function oauthAuthorizationOf(headers) {
|
|
3634
|
+
const value = singleHeader(headers, "authorization");
|
|
3635
|
+
return value?.startsWith(OAUTH_AUTHORIZATION_PREFIX) === true ? value : void 0;
|
|
3636
|
+
}
|
|
3632
3637
|
function sessionCreateId(body) {
|
|
3633
3638
|
let parsed;
|
|
3634
3639
|
try {
|
|
@@ -3772,7 +3777,7 @@ function createRcSessionTracker(deps) {
|
|
|
3772
3777
|
}
|
|
3773
3778
|
const tail = path29.slice(RC_SESSIONS_PATH_PREFIX.length);
|
|
3774
3779
|
const facts = {
|
|
3775
|
-
|
|
3780
|
+
oauthAuthorization: oauthAuthorizationOf(request4.headers),
|
|
3776
3781
|
anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
|
|
3777
3782
|
anthropicClientPlatform: singleHeader(request4.headers, "anthropic-client-platform")
|
|
3778
3783
|
};
|
|
@@ -3814,7 +3819,7 @@ function createRcSessionTracker(deps) {
|
|
|
3814
3819
|
}
|
|
3815
3820
|
const entry = entries.get(id) ?? birth(id, facts);
|
|
3816
3821
|
entry.lastSeenAt = deps.now();
|
|
3817
|
-
entry.
|
|
3822
|
+
entry.oauthAuthorization = facts.oauthAuthorization ?? entry.oauthAuthorization;
|
|
3818
3823
|
entry.anthropicVersion = facts.anthropicVersion ?? entry.anthropicVersion;
|
|
3819
3824
|
entry.anthropicClientPlatform = facts.anthropicClientPlatform ?? entry.anthropicClientPlatform;
|
|
3820
3825
|
const bodyKind = method === "POST" && rest === `${id}/worker/events` ? "worker-events" : method === "POST" && rest === `${id}/events` ? "client-events" : method === "POST" && rest === `${id}/worker/heartbeat` ? "heartbeat" : method === "PUT" && rest === `${id}/worker` ? "worker-registration" : void 0;
|
|
@@ -3902,7 +3907,7 @@ function createRcSessionTracker(deps) {
|
|
|
3902
3907
|
},
|
|
3903
3908
|
credentialOf: (sessionId) => {
|
|
3904
3909
|
const entry = entries.get(sessionId);
|
|
3905
|
-
return entry === void 0 ? void 0 : { authorization: entry.
|
|
3910
|
+
return entry === void 0 ? void 0 : { authorization: entry.oauthAuthorization, anthropicVersion: entry.anthropicVersion, anthropicClientPlatform: entry.anthropicClientPlatform };
|
|
3906
3911
|
},
|
|
3907
3912
|
completePending: (sessionId, requestId) => {
|
|
3908
3913
|
entries.get(sessionId)?.pending.delete(requestId);
|
|
@@ -4025,6 +4030,9 @@ function rcEventWriteResultFromAnswer(answer) {
|
|
|
4025
4030
|
}
|
|
4026
4031
|
return { ok: true, sequenceNums };
|
|
4027
4032
|
}
|
|
4033
|
+
function noOAuthCredentialResult(sessionId) {
|
|
4034
|
+
return { ok: false, message: `no claude.ai OAuth bearer has been observed for session ${sessionId}: only worker calls crossed this door, and the worker JWT they carry is answered 401 on the client half. Reconnect Remote Control through this door and the create's own bearer will be observed` };
|
|
4035
|
+
}
|
|
4028
4036
|
function rcWriteHeaders(credential) {
|
|
4029
4037
|
const headers = { "content-type": "application/json" };
|
|
4030
4038
|
if (credential.authorization !== void 0) {
|
|
@@ -4043,6 +4051,9 @@ async function injectRcUserMessage(deps, sessionId, text) {
|
|
|
4043
4051
|
if (credential === void 0) {
|
|
4044
4052
|
return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
|
|
4045
4053
|
}
|
|
4054
|
+
if (credential.authorization === void 0) {
|
|
4055
|
+
return noOAuthCredentialResult(sessionId);
|
|
4056
|
+
}
|
|
4046
4057
|
const body = JSON.stringify(buildRcEventWriteBody(buildRcUserMessagePayload(deps.newUuid(), sessionId, text)));
|
|
4047
4058
|
let answer;
|
|
4048
4059
|
try {
|
|
@@ -4061,6 +4072,9 @@ async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
|
4061
4072
|
if (credential === void 0) {
|
|
4062
4073
|
return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
|
|
4063
4074
|
}
|
|
4075
|
+
if (credential.authorization === void 0) {
|
|
4076
|
+
return noOAuthCredentialResult(sessionId);
|
|
4077
|
+
}
|
|
4064
4078
|
if (!deps.pendingOf(sessionId).some((pending) => pending.requestId === requestId)) {
|
|
4065
4079
|
return { ok: false, message: `the front door has not observed control request ${requestId} pending on session ${sessionId}: it was answered already (by this door or by an attached client), it passed its answer deadline (the protocol's permission round-trip bound), or it never passed through this door` };
|
|
4066
4080
|
}
|
|
@@ -4937,13 +4951,24 @@ function ensureHeadroom(params) {
|
|
|
4937
4951
|
const { paths, ports } = params;
|
|
4938
4952
|
const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
|
|
4939
4953
|
let spawnedSupervisor = false;
|
|
4954
|
+
let awaitingAllowlist = false;
|
|
4940
4955
|
for (; ; ) {
|
|
4941
4956
|
const state = readHeadroomState(ports.fs, paths.headroomStateFile);
|
|
4942
4957
|
if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
|
|
4943
4958
|
const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
|
|
4944
4959
|
if (daemonUp && state.socketPath !== void 0) {
|
|
4945
|
-
|
|
4946
|
-
|
|
4960
|
+
const required = params.requiredAllowlistHash?.();
|
|
4961
|
+
if (required === void 0 || state.allowlistHash === required) {
|
|
4962
|
+
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
|
|
4963
|
+
return { socketPath: state.socketPath };
|
|
4964
|
+
}
|
|
4965
|
+
const holders = sessionsForSupervisor(ports.fs, paths.headroomSessionsDir, state.supervisorPid).filter((session) => ports.isRunning(session.pid));
|
|
4966
|
+
if (holders.length > 0) {
|
|
4967
|
+
throw new HeadroomStartError(
|
|
4968
|
+
`agent-shim: the running headroom daemon was started before this launch's front door address and would refuse every request this launch sends through it. It restarts once the launches using it end (pid ${holders.map((session) => String(session.pid)).join(", ")}); end them and launch again, or launch with --no-headroom.`
|
|
4969
|
+
);
|
|
4970
|
+
}
|
|
4971
|
+
awaitingAllowlist = true;
|
|
4947
4972
|
}
|
|
4948
4973
|
if (state.lastError !== void 0) {
|
|
4949
4974
|
throw new HeadroomStartError(
|
|
@@ -4971,7 +4996,7 @@ function ensureHeadroom(params) {
|
|
|
4971
4996
|
if (ports.now() >= deadline) {
|
|
4972
4997
|
const lastError = state?.lastError;
|
|
4973
4998
|
throw new HeadroomStartError(
|
|
4974
|
-
`agent-shim: the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + `. Daemon log: ${paths.headroomLogPath}`
|
|
4999
|
+
`agent-shim: the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (awaitingAllowlist ? " (the running daemon's allowlist does not admit this launch's front door, and it did not restart)" : "") + `. Daemon log: ${paths.headroomLogPath}`
|
|
4975
5000
|
);
|
|
4976
5001
|
}
|
|
4977
5002
|
ports.sleep(HEADROOM_LAUNCHER_POLL_MS);
|
|
@@ -7270,10 +7295,11 @@ var realHeadroomSocketTrust = {
|
|
|
7270
7295
|
};
|
|
7271
7296
|
function realHeadroomPort(paths, options) {
|
|
7272
7297
|
return {
|
|
7273
|
-
ensure: () => {
|
|
7298
|
+
ensure: ({ routesProvider }) => {
|
|
7274
7299
|
const up = ensureHeadroom({
|
|
7275
7300
|
paths,
|
|
7276
7301
|
launcherPid: process.pid,
|
|
7302
|
+
...routesProvider ? { requiredAllowlistHash: () => hashAllowlist(currentHeadroomAllowlist(realFarmFs, paths)) } : {},
|
|
7277
7303
|
ports: {
|
|
7278
7304
|
fs: realFarmFs,
|
|
7279
7305
|
// Zombie-aware on purpose: a supervisor that died while still a child of this launcher sits unreaped until the launcher itself exits, and a defunct supervisor answering signal 0 as alive would stretch every launch to the full start timeout.
|
|
@@ -8957,7 +8983,7 @@ function prepareLaunch(params) {
|
|
|
8957
8983
|
let headroom;
|
|
8958
8984
|
const headroomPort = params.headroom;
|
|
8959
8985
|
if (resolvedFlags.headroom && headroomPort !== void 0) {
|
|
8960
|
-
headroom = headroomPort.ensure();
|
|
8986
|
+
headroom = headroomPort.ensure({ routesProvider: resolvedProvider !== void 0 });
|
|
8961
8987
|
const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
|
|
8962
8988
|
log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on unix socket ${headroom.socketPath} (${via}, project ${headroom.projectId})`);
|
|
8963
8989
|
} else if (resolvedFlags.headroom) {
|
package/dist/index.mjs
CHANGED
|
@@ -2548,7 +2548,7 @@ function readFrontDoorState(fs12, stateFile) {
|
|
|
2548
2548
|
}
|
|
2549
2549
|
function writeFrontDoorState(fs12, stateFile, state) {
|
|
2550
2550
|
fs12.mkdirp(path7.dirname(stateFile));
|
|
2551
|
-
fs12.
|
|
2551
|
+
fs12.writeFilePrivate(stateFile, `${JSON.stringify(state, null, 2)}
|
|
2552
2552
|
`);
|
|
2553
2553
|
}
|
|
2554
2554
|
function frontDoorOrigin(state) {
|
|
@@ -3445,6 +3445,11 @@ function singleHeader(headers, name) {
|
|
|
3445
3445
|
const value = headers[name];
|
|
3446
3446
|
return typeof value === "string" ? value : void 0;
|
|
3447
3447
|
}
|
|
3448
|
+
var OAUTH_AUTHORIZATION_PREFIX = "Bearer sk-ant-oat";
|
|
3449
|
+
function oauthAuthorizationOf(headers) {
|
|
3450
|
+
const value = singleHeader(headers, "authorization");
|
|
3451
|
+
return value?.startsWith(OAUTH_AUTHORIZATION_PREFIX) === true ? value : void 0;
|
|
3452
|
+
}
|
|
3448
3453
|
function sessionCreateId(body) {
|
|
3449
3454
|
let parsed;
|
|
3450
3455
|
try {
|
|
@@ -3588,7 +3593,7 @@ function createRcSessionTracker(deps) {
|
|
|
3588
3593
|
}
|
|
3589
3594
|
const tail = path29.slice(RC_SESSIONS_PATH_PREFIX.length);
|
|
3590
3595
|
const facts = {
|
|
3591
|
-
|
|
3596
|
+
oauthAuthorization: oauthAuthorizationOf(request4.headers),
|
|
3592
3597
|
anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
|
|
3593
3598
|
anthropicClientPlatform: singleHeader(request4.headers, "anthropic-client-platform")
|
|
3594
3599
|
};
|
|
@@ -3630,7 +3635,7 @@ function createRcSessionTracker(deps) {
|
|
|
3630
3635
|
}
|
|
3631
3636
|
const entry = entries.get(id) ?? birth(id, facts);
|
|
3632
3637
|
entry.lastSeenAt = deps.now();
|
|
3633
|
-
entry.
|
|
3638
|
+
entry.oauthAuthorization = facts.oauthAuthorization ?? entry.oauthAuthorization;
|
|
3634
3639
|
entry.anthropicVersion = facts.anthropicVersion ?? entry.anthropicVersion;
|
|
3635
3640
|
entry.anthropicClientPlatform = facts.anthropicClientPlatform ?? entry.anthropicClientPlatform;
|
|
3636
3641
|
const bodyKind = method === "POST" && rest === `${id}/worker/events` ? "worker-events" : method === "POST" && rest === `${id}/events` ? "client-events" : method === "POST" && rest === `${id}/worker/heartbeat` ? "heartbeat" : method === "PUT" && rest === `${id}/worker` ? "worker-registration" : void 0;
|
|
@@ -3718,7 +3723,7 @@ function createRcSessionTracker(deps) {
|
|
|
3718
3723
|
},
|
|
3719
3724
|
credentialOf: (sessionId) => {
|
|
3720
3725
|
const entry = entries.get(sessionId);
|
|
3721
|
-
return entry === void 0 ? void 0 : { authorization: entry.
|
|
3726
|
+
return entry === void 0 ? void 0 : { authorization: entry.oauthAuthorization, anthropicVersion: entry.anthropicVersion, anthropicClientPlatform: entry.anthropicClientPlatform };
|
|
3722
3727
|
},
|
|
3723
3728
|
completePending: (sessionId, requestId) => {
|
|
3724
3729
|
entries.get(sessionId)?.pending.delete(requestId);
|
|
@@ -3841,6 +3846,9 @@ function rcEventWriteResultFromAnswer(answer) {
|
|
|
3841
3846
|
}
|
|
3842
3847
|
return { ok: true, sequenceNums };
|
|
3843
3848
|
}
|
|
3849
|
+
function noOAuthCredentialResult(sessionId) {
|
|
3850
|
+
return { ok: false, message: `no claude.ai OAuth bearer has been observed for session ${sessionId}: only worker calls crossed this door, and the worker JWT they carry is answered 401 on the client half. Reconnect Remote Control through this door and the create's own bearer will be observed` };
|
|
3851
|
+
}
|
|
3844
3852
|
function rcWriteHeaders(credential) {
|
|
3845
3853
|
const headers = { "content-type": "application/json" };
|
|
3846
3854
|
if (credential.authorization !== void 0) {
|
|
@@ -3859,6 +3867,9 @@ async function injectRcUserMessage(deps, sessionId, text) {
|
|
|
3859
3867
|
if (credential === void 0) {
|
|
3860
3868
|
return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
|
|
3861
3869
|
}
|
|
3870
|
+
if (credential.authorization === void 0) {
|
|
3871
|
+
return noOAuthCredentialResult(sessionId);
|
|
3872
|
+
}
|
|
3862
3873
|
const body = JSON.stringify(buildRcEventWriteBody(buildRcUserMessagePayload(deps.newUuid(), sessionId, text)));
|
|
3863
3874
|
let answer;
|
|
3864
3875
|
try {
|
|
@@ -3877,6 +3888,9 @@ async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
|
3877
3888
|
if (credential === void 0) {
|
|
3878
3889
|
return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
|
|
3879
3890
|
}
|
|
3891
|
+
if (credential.authorization === void 0) {
|
|
3892
|
+
return noOAuthCredentialResult(sessionId);
|
|
3893
|
+
}
|
|
3880
3894
|
if (!deps.pendingOf(sessionId).some((pending) => pending.requestId === requestId)) {
|
|
3881
3895
|
return { ok: false, message: `the front door has not observed control request ${requestId} pending on session ${sessionId}: it was answered already (by this door or by an attached client), it passed its answer deadline (the protocol's permission round-trip bound), or it never passed through this door` };
|
|
3882
3896
|
}
|
|
@@ -4753,13 +4767,24 @@ function ensureHeadroom(params) {
|
|
|
4753
4767
|
const { paths, ports } = params;
|
|
4754
4768
|
const deadline = ports.now() + HEADROOM_START_TIMEOUT_MS;
|
|
4755
4769
|
let spawnedSupervisor = false;
|
|
4770
|
+
let awaitingAllowlist = false;
|
|
4756
4771
|
for (; ; ) {
|
|
4757
4772
|
const state = readHeadroomState(ports.fs, paths.headroomStateFile);
|
|
4758
4773
|
if (state?.supervisorPid !== void 0 && ports.isRunning(state.supervisorPid)) {
|
|
4759
4774
|
const daemonUp = state.socketPath !== void 0 && state.headroomPid !== void 0 && ports.isRunning(state.headroomPid);
|
|
4760
4775
|
if (daemonUp && state.socketPath !== void 0) {
|
|
4761
|
-
|
|
4762
|
-
|
|
4776
|
+
const required = params.requiredAllowlistHash?.();
|
|
4777
|
+
if (required === void 0 || state.allowlistHash === required) {
|
|
4778
|
+
writeSession(ports.fs, paths.headroomSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), supervisorPid: state.supervisorPid });
|
|
4779
|
+
return { socketPath: state.socketPath };
|
|
4780
|
+
}
|
|
4781
|
+
const holders = sessionsForSupervisor(ports.fs, paths.headroomSessionsDir, state.supervisorPid).filter((session) => ports.isRunning(session.pid));
|
|
4782
|
+
if (holders.length > 0) {
|
|
4783
|
+
throw new HeadroomStartError(
|
|
4784
|
+
`agent-shim: the running headroom daemon was started before this launch's front door address and would refuse every request this launch sends through it. It restarts once the launches using it end (pid ${holders.map((session) => String(session.pid)).join(", ")}); end them and launch again, or launch with --no-headroom.`
|
|
4785
|
+
);
|
|
4786
|
+
}
|
|
4787
|
+
awaitingAllowlist = true;
|
|
4763
4788
|
}
|
|
4764
4789
|
if (state.lastError !== void 0) {
|
|
4765
4790
|
throw new HeadroomStartError(
|
|
@@ -4787,7 +4812,7 @@ function ensureHeadroom(params) {
|
|
|
4787
4812
|
if (ports.now() >= deadline) {
|
|
4788
4813
|
const lastError = state?.lastError;
|
|
4789
4814
|
throw new HeadroomStartError(
|
|
4790
|
-
`agent-shim: the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + `. Daemon log: ${paths.headroomLogPath}`
|
|
4815
|
+
`agent-shim: the headroom daemon did not become ready within ${String(HEADROOM_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (awaitingAllowlist ? " (the running daemon's allowlist does not admit this launch's front door, and it did not restart)" : "") + `. Daemon log: ${paths.headroomLogPath}`
|
|
4791
4816
|
);
|
|
4792
4817
|
}
|
|
4793
4818
|
ports.sleep(HEADROOM_LAUNCHER_POLL_MS);
|
|
@@ -7086,10 +7111,11 @@ var realHeadroomSocketTrust = {
|
|
|
7086
7111
|
};
|
|
7087
7112
|
function realHeadroomPort(paths, options) {
|
|
7088
7113
|
return {
|
|
7089
|
-
ensure: () => {
|
|
7114
|
+
ensure: ({ routesProvider }) => {
|
|
7090
7115
|
const up = ensureHeadroom({
|
|
7091
7116
|
paths,
|
|
7092
7117
|
launcherPid: process.pid,
|
|
7118
|
+
...routesProvider ? { requiredAllowlistHash: () => hashAllowlist(currentHeadroomAllowlist(realFarmFs, paths)) } : {},
|
|
7093
7119
|
ports: {
|
|
7094
7120
|
fs: realFarmFs,
|
|
7095
7121
|
// Zombie-aware on purpose: a supervisor that died while still a child of this launcher sits unreaped until the launcher itself exits, and a defunct supervisor answering signal 0 as alive would stretch every launch to the full start timeout.
|
|
@@ -8773,7 +8799,7 @@ function prepareLaunch(params) {
|
|
|
8773
8799
|
let headroom;
|
|
8774
8800
|
const headroomPort = params.headroom;
|
|
8775
8801
|
if (resolvedFlags.headroom && headroomPort !== void 0) {
|
|
8776
|
-
headroom = headroomPort.ensure();
|
|
8802
|
+
headroom = headroomPort.ensure({ routesProvider: resolvedProvider !== void 0 });
|
|
8777
8803
|
const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
|
|
8778
8804
|
log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on unix socket ${headroom.socketPath} (${via}, project ${headroom.projectId})`);
|
|
8779
8805
|
} else if (resolvedFlags.headroom) {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1171,10 +1171,12 @@ interface HeadroomUp {
|
|
|
1171
1171
|
/**
|
|
1172
1172
|
* Everything the launcher needs from the headroom daemon, injected so its daemon-supervision side effects stay behind a port and the launcher's own logic stays pure over it (`src/realPorts.ts` wires the real one; tests wire fakes).
|
|
1173
1173
|
*
|
|
1174
|
-
* `ensure` brings the daemon up (spawning the detached supervisor when nothing healthy is running) and registers this launch in its session registry; `release` removes that registration when the spawned `claude` exits.
|
|
1174
|
+
* `ensure` brings the daemon up (spawning the detached supervisor when nothing healthy is running) and registers this launch in its session registry; `release` removes that registration when the spawned `claude` exits. `routesProvider` says the launch sends a provider's traffic through the daemon, which needs the daemon to have been started with the front door's current address on its allowlist: `ensure` then waits for a restart that brings it, or refuses when live sessions hold the stale daemon up, instead of registering against a daemon that would reject every request.
|
|
1175
1175
|
*/
|
|
1176
1176
|
interface HeadroomPort {
|
|
1177
|
-
readonly ensure: (
|
|
1177
|
+
readonly ensure: (options: Readonly<{
|
|
1178
|
+
routesProvider: boolean;
|
|
1179
|
+
}>) => HeadroomUp;
|
|
1178
1180
|
readonly release: () => void;
|
|
1179
1181
|
}
|
|
1180
1182
|
/**
|
|
@@ -1767,7 +1769,7 @@ declare function rcObserverAsPassthrough(observer: RcExchangeObserver): Passthro
|
|
|
1767
1769
|
declare function buildRcUserMessagePayload(uuid: string, sessionId: string, text: string): Record<string, unknown>;
|
|
1768
1770
|
/** Wraps payload event(s) in the write body the endpoint takes: `{"events": [{"payload": {...}}]}`. */
|
|
1769
1771
|
declare function buildRcEventWriteBody(payload: Record<string, unknown>): Record<string, unknown>;
|
|
1770
|
-
/** The headers a client-half write sends: the observed credential and protocol values, replayed verbatim, never invented. */
|
|
1772
|
+
/** The headers a client-half write sends: the observed OAuth-kind credential and protocol values, replayed verbatim, never invented. */
|
|
1771
1773
|
interface RcWriteHeaders {
|
|
1772
1774
|
readonly authorization: string | undefined;
|
|
1773
1775
|
readonly anthropicVersion: string | undefined;
|
|
@@ -2115,6 +2117,10 @@ declare function ensureHeadroom(params: {
|
|
|
2115
2117
|
readonly paths: LayoutPaths;
|
|
2116
2118
|
readonly launcherPid: number;
|
|
2117
2119
|
readonly ports: EnsureHeadroomPorts;
|
|
2120
|
+
/**
|
|
2121
|
+
* The hash of the allowlist the daemon must have been started with for this launch to work, read fresh on every poll because the front door's address it contains can change while the launch waits. Given for a launch that routes a provider through headroom, whose requests come back to the front door's direct origin and are refused by a daemon that was started without it; absent for a launch that only needs Claude Code's own API, which every daemon admits.
|
|
2122
|
+
*/
|
|
2123
|
+
readonly requiredAllowlistHash?: () => string;
|
|
2118
2124
|
}): {
|
|
2119
2125
|
readonly socketPath: string;
|
|
2120
2126
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-shim",
|
|
3
|
-
"version": "8.5.
|
|
3
|
+
"version": "8.5.3",
|
|
4
4
|
"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.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Joseph Mearman <joseph@mearman.co.uk>",
|