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.
Files changed (2) hide show
  1. package/dist/agent.js +106 -83
  2. 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
- args.nc.publish(args.responseSubject, sessionRpcCodec.encode(JSON.stringify(args.payload)));
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
- const initialAgentId = typeof natsBootstrap.agentId === "string" ? natsBootstrap.agentId : "";
3763
- if (!initialAgentId) {
3764
- throw new Error("agent id missing from bootstrap");
3765
- }
3766
- process.stdout.write(`\n[doer-agent v${agentVersion}]\n`);
3767
- if (!usesDefaultServer) {
3768
- process.stdout.write(`- server: ${serverBaseUrl}\n`);
3769
- }
3770
- process.stdout.write(`- userId: ${userId}\n`);
3771
- process.stdout.write(`- agentId: ${initialAgentId}\n`);
3772
- process.stdout.write(`\n- transport: nats\n`);
3773
- process.stdout.write(`- natsServers: ${jetstream.servers.join(",")}\n`);
3774
- process.stdout.write(`- natsStream: ${jetstream.stream}\n`);
3775
- process.stdout.write(`- natsSubject: ${jetstream.subject}\n`);
3776
- process.stdout.write(`- natsDurable: ${jetstream.durable}\n\n`);
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
- heartbeatHealthy = true;
3789
- })
3790
- .catch((error) => {
3791
- const message = error instanceof Error ? error.message : String(error);
3792
- if (heartbeatHealthy !== false) {
3793
- writeAgentInfraError(`heartbeat failed: ${message}`);
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
- heartbeatHealthy = false;
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
- }, 10_000);
3798
- subscribeToFsRpc({
3799
- jetstream,
3800
- serverBaseUrl,
3801
- userId,
3802
- agentId: initialAgentId,
3803
- agentToken,
3804
- });
3805
- subscribeToSessionRpc({
3806
- jetstream,
3807
- userId,
3808
- agentId: initialAgentId,
3809
- });
3810
- subscribeToCodexAuthRpc({
3811
- jetstream,
3812
- userId,
3813
- agentId: initialAgentId,
3814
- });
3815
- subscribeToSettingsRpc({
3816
- jetstream,
3817
- userId,
3818
- agentId: initialAgentId,
3819
- });
3820
- subscribeToGitRpc({
3821
- jetstream,
3822
- userId,
3823
- agentId: initialAgentId,
3824
- });
3825
- subscribeToRunRpc({
3826
- jetstream,
3827
- serverBaseUrl,
3828
- userId,
3829
- agentId: initialAgentId,
3830
- agentToken,
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doer-agent",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Reverse-polling agent runtime for doer",
5
5
  "type": "module",
6
6
  "main": "dist/agent.js",