doer-agent 0.2.7 → 0.2.8
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/agent.js +106 -83
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -115,13 +115,6 @@ async function initJetStreamContext(args) {
|
|
|
115
115
|
const nc = await connect(args.token ? { servers: args.servers, token: args.token } : { servers: args.servers });
|
|
116
116
|
const jsm = await nc.jetstreamManager();
|
|
117
117
|
await ensureJetStreamInfra({ jsm, stream, subject, durable });
|
|
118
|
-
void nc.closed().then((error) => {
|
|
119
|
-
if (error) {
|
|
120
|
-
writeAgentInfraError(`nats connection closed with error: ${error.message}`);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
writeAgentInfraError("nats connection closed cleanly");
|
|
124
|
-
});
|
|
125
118
|
void (async () => {
|
|
126
119
|
try {
|
|
127
120
|
for await (const status of nc.status()) {
|
|
@@ -3059,7 +3052,25 @@ async function deleteAgentSession(filePath, sessionId) {
|
|
|
3059
3052
|
}
|
|
3060
3053
|
}
|
|
3061
3054
|
function publishSessionRpcResponse(args) {
|
|
3062
|
-
|
|
3055
|
+
try {
|
|
3056
|
+
args.nc.publish(args.responseSubject, sessionRpcCodec.encode(JSON.stringify(args.payload)));
|
|
3057
|
+
}
|
|
3058
|
+
catch (error) {
|
|
3059
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3060
|
+
writeAgentError(`session rpc publish failed responseSubject=${args.responseSubject}: ${message}`);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
function stopAllSessionWatchers() {
|
|
3064
|
+
const stops = [...activeSessionWatchers.values()];
|
|
3065
|
+
for (const stop of stops) {
|
|
3066
|
+
try {
|
|
3067
|
+
stop();
|
|
3068
|
+
}
|
|
3069
|
+
catch (error) {
|
|
3070
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3071
|
+
writeAgentError(`session watcher cleanup failed: ${message}`);
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3063
3074
|
}
|
|
3064
3075
|
async function startSessionWatch(args) {
|
|
3065
3076
|
const resolvedFile = resolveSessionFilePath(args.filePath);
|
|
@@ -3753,85 +3764,97 @@ async function main() {
|
|
|
3753
3764
|
throw new Error("user-id and agent-secret are required");
|
|
3754
3765
|
}
|
|
3755
3766
|
const agentToken = agentSecret;
|
|
3756
|
-
const { natsBootstrap, jetstream } = await connectBootstrapWithRetry({
|
|
3757
|
-
serverBaseUrl,
|
|
3758
|
-
userId,
|
|
3759
|
-
agentToken,
|
|
3760
|
-
});
|
|
3761
3767
|
const agentVersion = await resolveAgentVersion();
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
process.stdout.write(`- workspace: ${process.cwd()}\n\n`);
|
|
3778
|
-
if (requestedServerBaseUrl !== serverBaseUrl) {
|
|
3779
|
-
writeAgentInfo(`detected container runtime, server endpoint rewritten: ${requestedServerBaseUrl} -> ${serverBaseUrl}`);
|
|
3780
|
-
}
|
|
3781
|
-
let heartbeatHealthy = null;
|
|
3782
|
-
const heartbeatTimer = setInterval(() => {
|
|
3783
|
-
void heartbeatAgent({ serverBaseUrl, userId, agentToken })
|
|
3784
|
-
.then(() => {
|
|
3785
|
-
if (heartbeatHealthy === false) {
|
|
3786
|
-
writeAgentInfraError(`heartbeat reconnected at=${formatLocalTimestamp()}`);
|
|
3768
|
+
let bannerShown = false;
|
|
3769
|
+
while (true) {
|
|
3770
|
+
const { natsBootstrap, jetstream } = await connectBootstrapWithRetry({
|
|
3771
|
+
serverBaseUrl,
|
|
3772
|
+
userId,
|
|
3773
|
+
agentToken,
|
|
3774
|
+
});
|
|
3775
|
+
const initialAgentId = typeof natsBootstrap.agentId === "string" ? natsBootstrap.agentId : "";
|
|
3776
|
+
if (!initialAgentId) {
|
|
3777
|
+
throw new Error("agent id missing from bootstrap");
|
|
3778
|
+
}
|
|
3779
|
+
if (!bannerShown) {
|
|
3780
|
+
process.stdout.write(`\n[doer-agent v${agentVersion}]\n`);
|
|
3781
|
+
if (!usesDefaultServer) {
|
|
3782
|
+
process.stdout.write(`- server: ${serverBaseUrl}\n`);
|
|
3787
3783
|
}
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
.
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3784
|
+
process.stdout.write(`- userId: ${userId}\n`);
|
|
3785
|
+
process.stdout.write(`- agentId: ${initialAgentId}\n`);
|
|
3786
|
+
process.stdout.write(`\n- transport: nats\n`);
|
|
3787
|
+
process.stdout.write(`- natsServers: ${jetstream.servers.join(",")}\n`);
|
|
3788
|
+
process.stdout.write(`- natsStream: ${jetstream.stream}\n`);
|
|
3789
|
+
process.stdout.write(`- natsSubject: ${jetstream.subject}\n`);
|
|
3790
|
+
process.stdout.write(`- natsDurable: ${jetstream.durable}\n\n`);
|
|
3791
|
+
process.stdout.write(`- workspace: ${process.cwd()}\n\n`);
|
|
3792
|
+
if (requestedServerBaseUrl !== serverBaseUrl) {
|
|
3793
|
+
writeAgentInfo(`detected container runtime, server endpoint rewritten: ${requestedServerBaseUrl} -> ${serverBaseUrl}`);
|
|
3794
3794
|
}
|
|
3795
|
-
|
|
3795
|
+
bannerShown = true;
|
|
3796
|
+
}
|
|
3797
|
+
else {
|
|
3798
|
+
writeAgentInfraError(`nats session restored agentId=${initialAgentId} servers=${jetstream.servers.join(",")} at=${formatLocalTimestamp()}`);
|
|
3799
|
+
}
|
|
3800
|
+
let heartbeatHealthy = null;
|
|
3801
|
+
const heartbeatTimer = setInterval(() => {
|
|
3802
|
+
void heartbeatAgent({ serverBaseUrl, userId, agentToken })
|
|
3803
|
+
.then(() => {
|
|
3804
|
+
if (heartbeatHealthy === false) {
|
|
3805
|
+
writeAgentInfraError(`heartbeat reconnected at=${formatLocalTimestamp()}`);
|
|
3806
|
+
}
|
|
3807
|
+
heartbeatHealthy = true;
|
|
3808
|
+
})
|
|
3809
|
+
.catch((error) => {
|
|
3810
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3811
|
+
if (heartbeatHealthy !== false) {
|
|
3812
|
+
writeAgentInfraError(`heartbeat failed: ${message}`);
|
|
3813
|
+
}
|
|
3814
|
+
heartbeatHealthy = false;
|
|
3815
|
+
});
|
|
3816
|
+
}, 10_000);
|
|
3817
|
+
subscribeToFsRpc({
|
|
3818
|
+
jetstream,
|
|
3819
|
+
serverBaseUrl,
|
|
3820
|
+
userId,
|
|
3821
|
+
agentId: initialAgentId,
|
|
3822
|
+
agentToken,
|
|
3796
3823
|
});
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
});
|
|
3832
|
-
await new Promise(() => {
|
|
3833
|
-
// Keep the long-lived agent process alive for RPC subscriptions and heartbeat.
|
|
3834
|
-
});
|
|
3824
|
+
subscribeToSessionRpc({
|
|
3825
|
+
jetstream,
|
|
3826
|
+
userId,
|
|
3827
|
+
agentId: initialAgentId,
|
|
3828
|
+
});
|
|
3829
|
+
subscribeToCodexAuthRpc({
|
|
3830
|
+
jetstream,
|
|
3831
|
+
userId,
|
|
3832
|
+
agentId: initialAgentId,
|
|
3833
|
+
});
|
|
3834
|
+
subscribeToSettingsRpc({
|
|
3835
|
+
jetstream,
|
|
3836
|
+
userId,
|
|
3837
|
+
agentId: initialAgentId,
|
|
3838
|
+
});
|
|
3839
|
+
subscribeToGitRpc({
|
|
3840
|
+
jetstream,
|
|
3841
|
+
userId,
|
|
3842
|
+
agentId: initialAgentId,
|
|
3843
|
+
});
|
|
3844
|
+
subscribeToRunRpc({
|
|
3845
|
+
jetstream,
|
|
3846
|
+
serverBaseUrl,
|
|
3847
|
+
userId,
|
|
3848
|
+
agentId: initialAgentId,
|
|
3849
|
+
agentToken,
|
|
3850
|
+
});
|
|
3851
|
+
const closeError = await jetstream.nc.closed();
|
|
3852
|
+
clearInterval(heartbeatTimer);
|
|
3853
|
+
stopAllSessionWatchers();
|
|
3854
|
+
const detail = closeError instanceof Error ? closeError.message : "clean close";
|
|
3855
|
+
writeAgentInfraError(`nats session ended: ${detail}; reconnecting`);
|
|
3856
|
+
await sleep(1000);
|
|
3857
|
+
}
|
|
3835
3858
|
}
|
|
3836
3859
|
main().catch((error) => {
|
|
3837
3860
|
const message = error instanceof Error ? error.message : String(error);
|